import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.Set; import java.util.TreeSet; /** This class finds all permutations of a specific * set of letters of a specific length. * * It also animates the process to more easily see * what is happening. * * @author Adam Blank * */ public class Permutations { public static final int HEIGHT = 700; public static final int WIDTH = 440; private static int outputX = 15; private static int outputY = 150; private static int numPrinted = 0; private static DrawingPanel panel; private static boolean paused = false; /** This string is global state that represents a * partially constructed solution. * * DO NOT DO THIS ON YOUR HOMEWORK. IT IS HORRIBLE * STYLE. We have only done it here, because it makes * the backtracking part more clear. */ private static String part; public static boolean hasUniqueCharacters(String str) { for (char c : str.toCharArray()) { if (str.indexOf(c) != str.lastIndexOf(c)) { return false; } } return true; } /** This method prints all the permutations of length n * using only the symbols a, b, c, and d. */ private static void permutations(int length) { String[] choices = { "a", "b", "c", "d" }; placePartial(part); if (hasUniqueCharacters(part)) { if (length == 0) { add(part); } else { for (String choice : choices) { part += choice; permutations(length - 1); part = part.substring(0, part.length() - 1); } } } } public static void main(String[] args) { panel = new DrawingPanel(WIDTH, HEIGHT); panel.addMouseListener((MouseListener) new MouseAdapter() { public void mouseClicked(MouseEvent e) { Permutations.paused = !Permutations.paused; } }); part = ""; drawUnderline(); permutations(4); } /** This method draws an underline to the top of the * DrawingPanel to help demonstrate recursive backtracking * via animation. */ public static void drawUnderline() { Graphics g = panel.getGraphics(); g.setColor(Color.RED); Font font = new Font("Arial", Font.PLAIN, 100); g.setFont(font); g.drawString("____", 100, 80); } /** This method draws the current partial string to the top * of the DrawingPanel to help demonstrate recursive backtracking * via animation. */ public static void placePartial(String x) { if (x.length() == 0) { return; } Graphics g = panel.getGraphics(); g.setColor(Color.BLACK); Font font = new Font("Arial", Font.PLAIN, 100); g.setFont(font); g.setColor(Color.WHITE); g.fillRect(10, 5, 100 + 55 * (4), 80); if (x.length() > 1) { g.setColor(Color.BLACK); g.drawString(x.substring(0, x.length() - 1), 100, 80); } g.setColor(Color.BLUE); g.drawString(x.substring(x.length() - 1), 100 + 57 * (x.length() - 1), 80); g.setColor(Color.BLACK); pause(); } /** This method draws the given string to the bottom of the * DrawingPanel where it represents a "found" solution. */ public static void add(String x) { Graphics g = panel.getGraphics(); Font font = new Font("Arial", Font.PLAIN, 20); g.setFont(font); g.drawString(x + ", ", outputX, outputY); outputX += 60; numPrinted++; if (numPrinted % 7 == 0) { outputY += 30; outputX = 15; } } /** This method causes the animation to pause until the * DrawingPanel is clicked. */ public static void pause() { panel.sleep(800); while (paused) { panel.sleep(200); } } }