Предикат для сопоставления списка (все возможности) без повторяющихся целых чисел, длины N и в пределах от 1 до N - PullRequest
0 голосов
/ 01 ноября 2010

Это для GNU-Prolog

У меня проблемы с получением определенного предиката для работы.Его функциональность заключается в том, что он соответствует списку целых чисел с доменом от 1 до N без дубликатов и длиной N.В основном, что я хочу сделать, это использовать в качестве входов и выходов:

| ?- row_valid(X, 3).

X = [1, 2, 3] ? ;
X = [1, 3, 2] ? ;
X = [2, 1, 3] ? ;
X = [2, 3, 1] ? ;
X = [3, 1, 2] ? ;
X = [3, 2, 1] ? ;

no

| ?- row_valid(X, 2).

X = [1, 2] ? ;
X = [2, 1] ? ;

no

| ?- row_valid(X, 1).

X = [1] ? ;

no

Но сейчас происходит вот что:

| ?- row_valid(X, 3).

X = [] ? ;

no

Это, вероятно, происходит из-за row_valid([], _). предикат у меня в коде.Однако я могу убедиться, что предикат соответствует правильно, так как:

| ?- row_valid([1,2,3], 3).

true ?

yes

Вот предикаты, определенные.Есть ли у вас какие-либо предложения о том, как я могу заставить это работать так, как я хочу?Спасибо за ваше время.

% row_valid/2: matches if list of integers has domain of 1 to N and is not duplicated
% 1 - list of integers
% 2 - N
row_valid([], _).
row_valid(Row, N) :-
    length(Row, N),                % length
    no_duplicates_within_domain(Row, 1, N),
    row_valid(RestRow, N).

% no_duplicates/1: matches if list doesn't have repeat elements
% 1 - list
no_duplicates([]).        % for empty list always true
no_duplicates([Element | RestElements]) :-
    \+ member(Element, RestElements),        % this element cannot be repeated in the list
    no_duplicates(RestElements).

% within_domain/3 : matches if list integers are within a domain
% 1 - list
% 2 - min
% 3 - max
within_domain(Integers, Min, Max) :-
    max_list(Integers, Max),
    min_list(Integers, Min).

% no_duplicates_within_domain/3: matches if list integers are within a domain and isn't repeated
% 1 - list
% 2 - min
% 3 - max
no_duplicates_within_domain(Integers, Min, Max) :-
    no_duplicates(Integers),
    within_domain(Integers, Min, Max). 

Ответы [ 2 ]

1 голос
/ 26 мая 2015

Как насчет следующего?

row_valid(Xs,N) :-
   length(Xs,N),
   fd_domain(Xs,1,N),
   fd_all_different(Xs),
   fd_labeling(Xs).

Запуск с GNU Prolog 1.4.4:

?- row_valid(Xs,N).          

N = 0
Xs = [] ? ;

N = 1
Xs = [1] ? ;

N = 2
Xs = [1,2] ? ;

N = 2
Xs = [2,1] ? ;

N = 3
Xs = [1,2,3] ? ;

N = 3
Xs = [1,3,2] ? ;

N = 3
Xs = [2,1,3] ? ;

N = 3
Xs = [2,3,1] ? ;

N = 3
Xs = [3,1,2] ? ;

N = 3
Xs = [3,2,1] ? ;

N = 4
Xs = [1,2,3,4] ?        % ...and so on...
0 голосов
/ 01 ноября 2010

Вот простой фрагмент кода, который делает это в SWI-Prolog. Я не знаю, предоставляет ли GNU-Prolog between/3 и permutation/2, поэтому, возможно, он не дает прямого ответа на ваш вопрос, но, возможно, он все еще может помочь вам в дальнейшем.

row_valid(List, N) :-
    findall(X, between(1, N, X), Xs),
    permutation(Xs, List).

Примеры использования:

?- row_valid(List, 0).
List = [].

?- row_valid(List, 1).
List = [1] ;
false.

?- row_valid(List, 2).
List = [1, 2] ;
List = [2, 1] ;
false.

?- row_valid(List, 3).
List = [1, 2, 3] ;
List = [2, 1, 3] ;
List = [2, 3, 1] ;
List = [1, 3, 2] ;
List = [3, 1, 2] ;
List = [3, 2, 1] ;
false.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...