Breadth First vs. Depth First Search

So, in preperation for the computer contest (which you may remember I qualified for a while back), I did a 9 poit (the highest amount) problem. Turns out… it was really difficult. Edit: By the way, for anybody who can’t tell… this is in Java. You will also need JDK 1.5 (uses scanner).

My teacher had no idea how to do it, and as we were leaving, he thought of the phrase “breadth vs. depth search,” but I don’t think he knew exactly how to program it.

So, I showed the problem to my dad, and he immediately knew about the search algorithm, but wasn’t so good at programming it.

It’s taken us about three hours, but I present to you… our finished project!

import java.util.*;
import java.io.*;

public class pr93 {
	public static void main (String args[]) throws IOException {
		Scanner scanner = new Scanner (new FileReader ("pr93.txt"));
		
		int dictionaryLength = scanner.nextInt();
		ArrayList<String> words = new ArrayList<String>();
		int testCases = scanner.nextInt();
		
		
		scanner.nextLine();
		
		for (int i=0; i<dictionaryLength; i++) {
			words.add(scanner.nextLine());
		}
		
		for (int i=0; i<testCases; i++) {
			ArrayList<Path> potentialPaths = new ArrayList<Path>();
			ArrayList<Path> newPaths = new ArrayList<Path>();
			
			boolean printed = false;
			
			String start = scanner.next();
			String goal = scanner.next();
			
			for (int j=0; j<words.size(); j++) {
				if (pr93.areLinked(words.get(j), start)) {
					Path path = new Path (start, words.get(j));
					potentialPaths.add(path);
				}
			}
			
			for (int j=0; j<words.size()&&printed==false; j++) {					
				for (int m=0; m<potentialPaths.size(); m++) {
					if (potentialPaths.get(m).isFinished(goal)) {
						potentialPaths.get(m).printPath();
						printed = true;
						break;
					}
				}
				
				potentialPaths = pr93.buildNewPaths(words, potentialPaths, newPaths);
			}
			
			System.out.println();
		}
	}
	
	public static boolean areLinked (String word1, String word2) {
		int different = 0;
		StringBuffer wordOne = new StringBuffer(word1);
		StringBuffer wordTwo = new StringBuffer(word2);
		
		for (int i=0; i<word1.length(); i++) {
			if (wordOne.charAt(i)!=wordTwo.charAt(i)) {
				different++;
				
				if (different>1) return false;
			}
		}
		
		if (different==0) {
			return false;
		}
		
		return true;
	}
	
	public static ArrayList<Path> buildNewPaths (ArrayList<String> words, ArrayList<Path> oldPaths, ArrayList<Path> newPaths) {
		for (int j=0; j<oldPaths.size(); j++) {
			String lastWord = oldPaths.get(j).lastWord();			
			for (int m=0; m<words.size(); m++) {
				
				if (pr93.areLinked(lastWord, words.get(m)) &&
					!oldPaths.get(j).hasWord(words.get(m))) {
						Path newPath = new Path(oldPaths.get(j), words.get(m));
						newPaths.add(newPath);
				}
			}
		}
		
		return newPaths;
	}
}

class Path {
	ArrayList<String> path = new ArrayList<String>();
	
	public Path (String start, String end) {
		path.add(start);
		path.add(end);
	}
	
	public Path (Path oldPath, String word) {
		path = new ArrayList<String>(oldPath.getPath());
		path.add(word);
	}
	
	public void add (String word) {
		path.add(word);
	}
	
	public ArrayList<String> getPath () {
		return path;
	}
	
	public void printPath () {		
		for (int i=0; i<path.size(); i++) {
			System.out.println(path.get(i));
		}
	}
	
	public String toString () {
		return path.toString();
	}
	
	public String lastWord () {
		return path.get(path.size()-1);
	}
	
	public boolean isFinished (String goal) {
		if (path.get(path.size()-1).equals(goal)) {
			return true;
		}
		
		return false;
	}
	
	public boolean hasWord (String word) {
		return path.contains(word);
	}
}

[size=4]USAGE[/size]

It’s actually really simple. Given a dictionary, it will find the shortest path between two words. The sample input looks like this:

8 3
that
this
what
then
when
than
thin
thus
this that
what when
when then

The 8 represents the number of words in the dictionary (always all the same length), and the three represents how many chains you will need to find.

The sample output looks like this:

this
thin
than
that

what
that
than
then
when

when
then

Huzzah!

[whisper]I also could have taken the brute-force approach, but ■■■■ that wouldn’t have been nearly as pretty![/whisper]

I don’t get it :frowning:

It’ll find a chain of words with only one letter different…

Hmm that is pretty interesting. I’ve never seen anything like it before.

Yeah, I’m proud. It was hard. :smiley:

That is super cool dude!

Hehe. Thanks :smiley:

thats bloody cool nokrev - we used to do this as kids on rainy days…(sad childhood i had!!!) … very good example of java. mind converting it to AScript for me? :smirk2:

Err… I don’t know AS… I don’t use Flash.

I suppose this could be developed further to solve word-chain puzzles, i.e. where you transform one word into another word, e.g. slow to fast, warm to cold, hard to easy.
Viz. cat --> can --> con --> cog --> dog.

n.b. only one letter can altered at a time and the order of the letters can’t be changed.

[SIZE=“1”]Sorry, I couldn’t resist practising the use of so many abbreviations[/SIZE] :smiley:


Mazda Mxr-01

which is exacley what this thing does… is it not?

Yeah, that’s exactly what it does. :wink: