如何通过prolog中的输入来填充谓词的参数?
我有以下代码:如何通过prolog中的输入来填充谓词的参数?,prolog,crossword,Prolog,Crossword,我有以下代码: size(5). black(1,3). black(2,3). black(3,2). black(4,3). black(5,1). black(5,5). words([do,ore,ma,lis,ur,as,po, so,pirus, oker,al,adam, ik]) . :- use_module(library(lists),[nth1/3, select/3]). crossword(Puzzle) :- words(WordList),
size(5).
black(1,3).
black(2,3).
black(3,2).
black(4,3).
black(5,1).
black(5,5).
words([do,ore,ma,lis,ur,as,po, so,pirus, oker,al,adam, ik]) .
:- use_module(library(lists),[nth1/3, select/3]).
crossword(Puzzle) :-
words(WordList),
word2chars(WordList,CharsList),
make_empty_words(EmptyWords) ,
fill_in(CharsList,EmptyWords),
word2chars(Puzzle,EmptyWords).
word2chars([],[]).
word2chars([Word|RestWords] ,[Chars|RestChars] ) :-
atom_chars(Word,Chars),
word2chars(RestWords,RestChars).
fill_in([],[]).
fill_in([Word|RestWords],Puzzle) :-
select(Word,Puzzle,RestPuzzle),
fill_in(RestWords,RestPuzzle).
make_empty_words(EmptyWords) :-
size(Size),
make_puzzle(Size,Puzzle),
findall(black(I,J),black(I,J),Blacks) ,
fillblacks(Blacks,Puzzle),
empty_words(Puzzle,EmptyWords).
make_puzzle(Size,Puzzle) :-
length(Puzzle,Size),
make_lines(Puzzle,Size).
make_lines([],_).
make_lines([L|Ls],Size) :-
length(L,Size),
make_lines(Ls,Size).
fillblacks([],_).
fillblacks([black(I,J)|Blacks],Puzzle) :-
nth1(I,Puzzle,LineI),
nth1(J,LineI,black),
fillblacks(Blacks,Puzzle).
empty_words(Puzzle,EmptyWords) :-
empty_words(Puzzle,EmptyWords,TailEmptyWords),
size(Size),
transpose(Size,Puzzle,[],TransposedPuzzle),
empty_words(TransposedPuzzle,TailEmptyWords,[] ).
empty_words([],Es,Es).
empty_words([L|Ls],Es,EsTail) :-
empty_words_on_one_line(L,Es,Es1) ,
empty_words(Ls,Es1,EsTail).
empty_words_on_one_line([], Tail, Tail).
empty_words_on_one_line([V1,V2|L],[[V1,V2|Vars]|R],Tail) :-
var(V1), var(V2), !,
more_empty(L,RestL,Vars),
empty_words_on_one_line(RestL,R,Tail) .
empty_words_on_one_line([_| RestL],R, Tail) :-
empty_words_on_one_line(RestL,R,Tail) .
more_empty([],[],[]).
more_empty([V|R],RestL,Vars) :-
( var(V) ->
Vars = [V|RestVars],
more_empty(R,RestL,RestVars)
;
RestL = R,
Vars = []
).
transpose(N,Puzzle,Acc,TransposedPuzzle) :-
( N == 0 ->
TransposedPuzzle = Acc
;
nth_elements(N,Puzzle,OneVert),
M is N - 1,
transpose(M,Puzzle,[OneVert|Acc], TransposedPuzzle)
).
nth_elements(_,[],[]).
nth_elements(N,[X|R],[NthX| S]) :-
nth1(N,X,NthX),
nth_elements(N,R,S).
它用于解决这样的填字游戏:
black(Y1,X1).
black(Y2,X2).
black(Y3,X3).
black(Y4,X4).
black(Y5,X5).
black(Y6,X6).
crossword(Puzzle,Y1,X1,Y2,X2,...) :-
words(WordList),
word2chars(WordList,CharsList),
make_empty_words(EmptyWords,Size) ,
fill_in(CharsList,EmptyWords),
word2chars(Puzzle,EmptyWords).
默认情况下,代码中会给出黑色方块的位置,但我想找到一种方法,在查询纵横字谜时,通过输入给出黑色方块的位置
大概是这样的:
black(Y1,X1).
black(Y2,X2).
black(Y3,X3).
black(Y4,X4).
black(Y5,X5).
black(Y6,X6).
crossword(Puzzle,Y1,X1,Y2,X2,...) :-
words(WordList),
word2chars(WordList,CharsList),
make_empty_words(EmptyWords,Size) ,
fill_in(CharsList,EmptyWords),
word2chars(Puzzle,EmptyWords).
正如@Lougler提到的,我尝试重写代码,并将黑色方块作为输入输入程序,如下所示:
:- use_module(library(lists),[nth1/3, select/3]).
crossword(Puzzle,Size,Blacks,WordList) :-
word2chars(WordList,CharsList),
make_empty_words(EmptyWords,Size,Blacks) ,
fill_in(CharsList,EmptyWords),
word2chars(Puzzle,EmptyWords).
word2chars([],[]).
word2chars([Word|RestWords] ,[Chars|RestChars] ) :-
atom_chars(Word,Chars),
word2chars(RestWords,RestChars).
fill_in([],[]).
fill_in([Word|RestWords],Puzzle) :-
select(Word,Puzzle,RestPuzzle),
fill_in(RestWords,RestPuzzle).
make_empty_words(EmptyWords,Size,Blacks) :-
make_puzzle(Size,Puzzle),
fillblacks(Blacks,Puzzle),
empty_words(Puzzle,EmptyWords).
make_puzzle(Size,Puzzle) :-
length(Puzzle,Size),
make_lines(Puzzle,Size).
make_lines([],_).
make_lines([L|Ls],Size) :-
length(L,Size),
make_lines(Ls,Size).
fillblacks([],_).
fillblacks([black(I,J)|Blacks],Puzzle) :-
nth1(I,Puzzle,LineI),
nth1(J,LineI,black),
fillblacks(Blacks,Puzzle).
empty_words(Puzzle,EmptyWords) :-
empty_words(Puzzle,EmptyWords,TailEmptyWords),
transpose(Size,Puzzle,[],TransposedPuzzle),
empty_words(TransposedPuzzle,TailEmptyWords,[] ).
empty_words([],Es,Es).
empty_words([L|Ls],Es,EsTail) :-
empty_words_on_one_line(L,Es,Es1) ,
empty_words(Ls,Es1,EsTail).
empty_words_on_one_line([], Tail, Tail).
empty_words_on_one_line([V1,V2|L],[[V1,V2|Vars]|R],Tail) :-
var(V1), var(V2), !,
more_empty(L,RestL,Vars),
empty_words_on_one_line(RestL,R,Tail) .
empty_words_on_one_line([_| RestL],R, Tail) :-
empty_words_on_one_line(RestL,R,Tail) .
more_empty([],[],[]).
more_empty([V|R],RestL,Vars) :-
( var(V)
-> Vars = [V|RestVars],
more_empty(R,RestL,RestVars)
; RestL = R,
Vars = []
).
transpose(N,Puzzle,Acc,TransposedPuzzle) :-
( N == 0
-> TransposedPuzzle = Acc
; nth_elements(N,Puzzle,OneVert),
M is N - 1,
transpose(M,Puzzle,[OneVert|Acc], TransposedPuzzle)
).
nth_elements(_,[],[]).
nth_elements(N,[X|R],[NthX| S]) :-
nth1(N,X,NthX),
nth_elements(N,R,S).
现在,通过以下输入,代码返回谜题的答案:
crossword(Puzzle,5,[black(1,3),black(2,3),black(3,2),black(4,3),
black(5,1),black(5,5)],[do,ore,ma,lis,ur,as,pu, so,pirus, uker,al,adam, ik]).
输出将是:
Puzzle = [as,pu,do,ik,ore,ma,ur,lis,adam,so,al,pirus,uker]
正如@Lougler提到的,我尝试重写代码,并将黑色方块作为输入输入程序,如下所示:
:- use_module(library(lists),[nth1/3, select/3]).
crossword(Puzzle,Size,Blacks,WordList) :-
word2chars(WordList,CharsList),
make_empty_words(EmptyWords,Size,Blacks) ,
fill_in(CharsList,EmptyWords),
word2chars(Puzzle,EmptyWords).
word2chars([],[]).
word2chars([Word|RestWords] ,[Chars|RestChars] ) :-
atom_chars(Word,Chars),
word2chars(RestWords,RestChars).
fill_in([],[]).
fill_in([Word|RestWords],Puzzle) :-
select(Word,Puzzle,RestPuzzle),
fill_in(RestWords,RestPuzzle).
make_empty_words(EmptyWords,Size,Blacks) :-
make_puzzle(Size,Puzzle),
fillblacks(Blacks,Puzzle),
empty_words(Puzzle,EmptyWords).
make_puzzle(Size,Puzzle) :-
length(Puzzle,Size),
make_lines(Puzzle,Size).
make_lines([],_).
make_lines([L|Ls],Size) :-
length(L,Size),
make_lines(Ls,Size).
fillblacks([],_).
fillblacks([black(I,J)|Blacks],Puzzle) :-
nth1(I,Puzzle,LineI),
nth1(J,LineI,black),
fillblacks(Blacks,Puzzle).
empty_words(Puzzle,EmptyWords) :-
empty_words(Puzzle,EmptyWords,TailEmptyWords),
transpose(Size,Puzzle,[],TransposedPuzzle),
empty_words(TransposedPuzzle,TailEmptyWords,[] ).
empty_words([],Es,Es).
empty_words([L|Ls],Es,EsTail) :-
empty_words_on_one_line(L,Es,Es1) ,
empty_words(Ls,Es1,EsTail).
empty_words_on_one_line([], Tail, Tail).
empty_words_on_one_line([V1,V2|L],[[V1,V2|Vars]|R],Tail) :-
var(V1), var(V2), !,
more_empty(L,RestL,Vars),
empty_words_on_one_line(RestL,R,Tail) .
empty_words_on_one_line([_| RestL],R, Tail) :-
empty_words_on_one_line(RestL,R,Tail) .
more_empty([],[],[]).
more_empty([V|R],RestL,Vars) :-
( var(V)
-> Vars = [V|RestVars],
more_empty(R,RestL,RestVars)
; RestL = R,
Vars = []
).
transpose(N,Puzzle,Acc,TransposedPuzzle) :-
( N == 0
-> TransposedPuzzle = Acc
; nth_elements(N,Puzzle,OneVert),
M is N - 1,
transpose(M,Puzzle,[OneVert|Acc], TransposedPuzzle)
).
nth_elements(_,[],[]).
nth_elements(N,[X|R],[NthX| S]) :-
nth1(N,X,NthX),
nth_elements(N,R,S).
现在,通过以下输入,代码返回谜题的答案:
crossword(Puzzle,5,[black(1,3),black(2,3),black(3,2),black(4,3),
black(5,1),black(5,5)],[do,ore,ma,lis,ur,as,pu, so,pirus, uker,al,adam, ik]).
输出将是:
Puzzle = [as,pu,do,ik,ore,ma,ur,lis,adam,so,al,pirus,uker]
非常好,+1用于自己解决 此外,我还想向您展示如何使用DCGs获取空单词/2及其相关谓词的参数较少的谓词,因此这些谓词更容易理解。此外,transpose/2在SICStus Prolog中已经作为库谓词提供,如果您对它的实现方式感兴趣,请参阅其源代码,因此我使用它。请注意,大小/1不再是必需的
:- use_module(library(clpfd)). % for transpose/2 in SWI-Prolog
empty_words(Puzzle,EmptyWords) :-
phrase(empty_words(Puzzle), EmptyWords, RestEmptyWords),
transpose(Puzzle, TransposedPuzzle),
phrase(empty_words(TransposedPuzzle), RestEmptyWords).
empty_words([]) --> [].
empty_words([L|Ls]) --> empty_words_on_one_line(L), empty_words(Ls).
empty_words_on_one_line([]) --> [].
empty_words_on_one_line([V1,V2|Ls0]) -->
{ var(V1), var(V2) }, !,
[[V1,V2|Vars]],
{ more_empty(Ls0, Ls, Vars) },
empty_words_on_one_line(Ls) .
empty_words_on_one_line([_|Ls]) --> empty_words_on_one_line(Ls).
其他谓词保持不变
您的填写/2以排列/2的形式提供
maplist/2可以在其他地方帮助您,例如:
maplist(length_list(Size), Puzzle)
将make_line/2替换为长度的简短定义\u list/2,我只留下一个简单的练习。非常好,+1用于自己解决它 此外,我还想向您展示如何使用DCGs获取空单词/2及其相关谓词的参数较少的谓词,因此这些谓词更容易理解。此外,transpose/2在SICStus Prolog中已经作为库谓词提供,如果您对它的实现方式感兴趣,请参阅其源代码,因此我使用它。请注意,大小/1不再是必需的
:- use_module(library(clpfd)). % for transpose/2 in SWI-Prolog
empty_words(Puzzle,EmptyWords) :-
phrase(empty_words(Puzzle), EmptyWords, RestEmptyWords),
transpose(Puzzle, TransposedPuzzle),
phrase(empty_words(TransposedPuzzle), RestEmptyWords).
empty_words([]) --> [].
empty_words([L|Ls]) --> empty_words_on_one_line(L), empty_words(Ls).
empty_words_on_one_line([]) --> [].
empty_words_on_one_line([V1,V2|Ls0]) -->
{ var(V1), var(V2) }, !,
[[V1,V2|Vars]],
{ more_empty(Ls0, Ls, Vars) },
empty_words_on_one_line(Ls) .
empty_words_on_one_line([_|Ls]) --> empty_words_on_one_line(Ls).
其他谓词保持不变
您的填写/2以排列/2的形式提供
maplist/2可以在其他地方帮助您,例如:
maplist(length_list(Size), Puzzle)
将make_line/2替换为长度的简短定义_list/2,我只留下一个简单的练习。最简单的方法可能是使用assertz,因此一旦提供了Y1和X1,就可以使用assertzblackY1、X1等。另一种方法需要更多地重写一些代码:将黑色方块作为列表参数传递,而不是使用findall来确定列表。我使用了第二种方法,现在它可以工作了,谢谢@louger。最简单的方法可能是使用assertz,所以一旦提供了Y1和X1,就可以使用assertzblackY1、X1等。另一种方法需要对一些代码进行更多的重写:将黑色方块作为列表参数传递,而不是使用findall来确定列表。我使用了第二种方法,现在可以使用了,谢谢@louger.Good job+1。另外,现在您将size作为参数传入,sizeX。子句不起任何作用,所以它可以被删除。你是对的@Lougler,我从代码中删除了它。谢谢你提到它。干得好+1。另外,现在您将size作为参数传入,sizeX。子句不起任何作用,所以它可以被删除。你是对的@Lougler,我从代码中删除了它。谢谢你提到它。