我正在创建一个程序,它将采用单词列表以及方格,纵横填字格式的空格网格,并返回唯一的解决方案,即填充填字游戏,使所有言语融贯一致。网格的大小是任意的,但它总是一个正方形。追溯纵横字谜拼图中的列表
在这里看到的是什么,我试图做一个例子: http://en.wikipedia.org/wiki/Fill-In_(puzzle)
我的程序下来的肉。从本质上讲,我的第一套谓词采用网格,并为每个插槽创建逻辑变量,忽略黑屏槽(#s)。然后,我创建一个长度超过1个插槽的可能单词列表(单个字母长的单词无效)。结果是具有形状的网格(一个非常简单的例子):
#_#
___
#_#
其中每行是从顶部到底部的“益智列表”的一个元素,即
Row 1 Row 2 Row 3
[[#,_,#],[_,_,_],[#,_,#]]
将充满像这样无逻辑变量:
#X#
ABC
#Z#
这个名单看起来就像(0部分):
[[#,X,#],[A,B,C],[#,Z,#]]
然后,形式的单词表:
[['M','E','N'],['N','E','W']]
是给定的,与最终的解决方案是
#M#
NEW
#N#
到目前为止,我充满了变数电网列表中0部分,并同时填写(“槽列表”),其中为每个长度超过1个空间长度的垂直和水平空间串(对于该示例)制作槽:
[[A,B,C],[X,B,Z]]
所以我成功地进行了这些设置,这样将一个单词统一到插槽列表的一个插槽中,也可以将该单词统一到拼图列表中的匹配变量。
现在,所有的输入将是这样的,总是只有一种方法来安排网格中的单词(不像这个例子中有两种方式,只是忽略),所以只有一个解决方案将由完成的程序(解决方案是填充的拼图网格)。
字,统一的算法应该是:
1. Take a word from the word list
2. Go through the slot list and unify with the first slot that succeeds
3. If there are no successful bindings, fail and backtrack to try a new
set of unifications
4. Keep failing and backtracking until a solution is found such that all
words bind successfully
我对这个统一的话插槽的代码如下:
%%% Takes a word (W) and a list of slots (S|Ss) and attempts to bind it to a slot
bind_word(W,[S|Ss],Slots):- bind_w(W,[S|Ss],[],Slots).
bind_w(_,[],Acc,Acc).
bind_w(W,[S|Ss],Acc,Slots):-
( W = S -> % Does the word bind to the next slot?
append(Acc,[S],Acc1), % YES Add the bound slot to the accumulator
append(Acc1,Ss,Acc2), % Add the rest of the slots to the accumulator
bind_w(_,[],Acc2,Slots) % Exit with success
; length(Ss,0) -> fail % NO Word doesn't bind, if there are no slots left to bind then this has failed
; append(Acc,[S],Acc1), % NO Word doesn't bind, but there are slots left, append this unbound slot to the accumulator
bind_w(W,Ss,Acc1,Slots) % Move to the next slot
).
%%%
我希望它做的是如果它击中
length(Ss,0) -> fail
然后回溯到开始处并再次尝试,但不要再次尝试使用相同的绑定,请考虑成功绑定为失败并跳过它们,例如:
1. Try to bind the word B,E,N to the first slot, and it works
2. Try to bind the word M,A,X to the second slot, and it doesn't
work and there are no slots left
3. Backtrack to (1), and instead of binding BEN to slot one (which
succeeded before), skip to the next slot and try unifying BEN to
the second slot.
不幸的是,当它击中
length(Ss,0) -> fail
它认为整个事情是一个失败,不会走回头路,但没有一切。求解谓词如下:
%%% Takes a puzzle grid and a wordlist and solves the puzzle
solve_puzzle(Solution, [], Solution).
solve_puzzle(Puzzle, Wordlist, Solved):-
fill_slots_H(Puzzle,Slots1,Puzzle1), % Fill out the puzzle with logical variables in every blank space (results = Puzzle1), also get all the horizontal word slots (results = Slots1)
flip(Puzzle1,0,Puzzle1_Flipped), % Flip the puzzle for vertical use (results = Puzzle1_Flipped)
fill_slots_V(Puzzle1_Flipped,Slots1,Slots), % Take the vertical puzzle and append the slots for vertical words onto the end of the existing slot list SLOTS IS THE FINAL UNBOUND SLOT LIST
flip(Puzzle1_Flipped,1,Puzzle_Final), % Flip the puzzle back to normal PUZZLE_FINAL IS THE FINAL UNBOUND PUZZLE
!, % Make these choices final
insert_words(Wordlist,Slots,Final_Slotlist),% Insert all the words into the slots and return the finished slot list
Slots = Final_Slotlist, % Bind all logical variables in the final slotlist to the slotlist linked to the puzzle
solve_puzzle(Puzzle_Final, [], Solved). % Puzzle is now filled, return it as the solution
%%%
%%% Takes a (W)ordlist, and (S)lot list and binds every word to a slot until the puzzle is finished
insert_words([],Slots,Slots).
insert_words([W|Ws], Current_Slotlist, Filled_Slotlist):-
bind_word(W,Current_Slotlist,Partial_Slotlist),
insert_words(Ws, Partial_Slotlist, Filled_Slotlist).
%%%
我填写的难题,获得水平字时隙列表,然后转拼图,并得到垂直字插槽(其附加到水平之一)的列表。然后,我用单词填充插槽列表,将填充列表与空插槽列表(也将单词统一到拼图网格)统一,然后返回完成的拼图。
我该如何做到这一点,如果它不能统一一个词,它回溯并跳过任何成功并尝试另一种选择?我想过尝试绑定,然后如果失败,随机选择单词列表并重试,但这听起来并不是很逻辑驱动的...
在此先感谢。
感谢您的输入;不过,我其实已经事先弄清楚了。 – jonogilmour 2014-10-09 04:48:46