私は現在、一度に 1 文字だけを変更することによって単語から別の単語に移動する単語のはしごを構築する課題に取り組んでいます [もちろん、実際の単語であることは維持しています]。
問題はこの方法にあると思います-幅優先探索を使用してツリーをトラバースすることにより、2つの単語間のリンクを見つけます。hereの説明を真似てアルゴリズムを実装しましたが、テストで得られるソリューションは最適ではありません。例 [言う人、支払う人、マナーを明らかに見逃す可能性があります]:
Discovery: link found, 6 words
layer
sayer
payer
mayer
mayor
manor
major
理想的なシナリオは次のとおりです。
Discovery: link found, 3 words
layer
mayer
mayor
major
このコードのデバッグを試みましたが、多くのループが含まれているため、問題を解決する方法としてはあまり現実的ではありません。
いくつかの指針:
- [connectionLink()] の進行に合わせてグラフを生成し、時間を節約します。
- このメソッドが含まれるクラスは、すべてのノード [グラフ内のポイント] を Hashtable に格納します。キーは単語であり、オブジェクトは単語のオブジェクトです。
Node は、接続されている Node のリスト、訪問されたかどうかのブール値、および文字列としての単語自体を格納します。
/* * @return String Returning a String listing words traversed to the goal * @param fW First word * @param sW Second word */ public String discovery(String fW,String sW){ String result="Discovery: no link found"; StringBuffer links=new StringBuffer(); int i=0; Queue<Node> queue=new LinkedList<Node>(); // Breadth first search uses a queue queue.add(hash.get(fW)); // Root of the tree, tree generated on the fly while(!queue.isEmpty()){ Node current=(Node)queue.poll(); if(!current.getVisited()){ current.setVisited(true); // Making sure it's only cycled once if(current.getWord().equals(sW)){ // Goal state while(current.getParent()!=null){ // Generating the list words traversed i++; links.insert(0,"\n"+current.getParent().getWord()); current=current.getParent(); } result="Discovery: link found, "+i+" words"+links.toString()+"\n"+sW; System.out.println(result); break; } else{ connectionLink(current.getWord()); // Finding connections for(Node node:current.getConnections()){ // Getting the connections of the Node if(!node.getVisited()){ // If child Node isn't visited, add to queue node.setParent(current); // Sets parent as Node just left queue.add(node); // Adding Node to queue // System.out.println("Discovery: adding "+node.getWord()+" to queue. Child of "+node.getParent().getWord()); // System.out.println("Discovery: current queue - "+queue.toString()); } } } } } clearVisited(); return result; }
ノード[標準のゲッターと設定もあります]:
public class Node{
private String word; // The data of the Node
private Node parent;
private LinkedList<Node> children; // Holds children
private boolean visited=false;
public Node(String word){
this.word=word.toLowerCase();
children=new LinkedList<Node>();
}
/*
* @param other Connecting to another Node - adding a child
*/
public void connectTo(Node other){
if(!(children.contains(other))&&!(this==other)) children.add(other);
}
}
接続を生成するメソッド。ここで、wordDifference は単語の文字が異なることをチェックするメソッドであり、そのテストに基づいてブール値を返します。
/*
* @param fW Finding the links of the inputted String
*/
public void connectionLink(String fW){
// dKS=discoveryKeys enum, dK=discoveryKey
Enumeration<String> dKS=hash.keys();
while(dKS.hasMoreElements()){ // Loop checks the word against every other word
String dK2=dKS.nextElement();
if(wordDifference(hash.get(fW),hash.get(dK2))){
(hash.get(fW)).connectTo(hash.get(dK2));
// System.out.println("Linking: "+hash.get(fW).getWord()+" & "+hash.get(dK2).getWord());
}
}
}
どんな助けでも大歓迎です。このコードには実際には何も問題がない可能性があります。問題は別の場所にある可能性がありますが、事前に感謝します。
主な問題は、これが最適な [最短経路] 結果を生成していないことです。[例のように] 目標に到達するために不要な単語を経由しています。幅優先検索の実装に何か問題がありますか [最適である必要があります]?