Hey guys,
I am new to Java and am having trouble finishing the class methods in Hole.java. I was provided reconstructor and glass. I was also told that the methods in glass are similar to those in hole. I was able to figure out some but I think I completely messed up others. Any help or tips would be welcomed.
Thank you
Reconstructor.java
package StainedGlass; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.Arrays; import java.util.Comparator; public class Reconstructor { private Glass[] pieces; private Hole window; private boolean solved; public Reconstructor(BufferedReader input) throws IOException { solved = false; readSilhouettes(input); } private void readSilhouettes(BufferedReader input) { final int MAXPIECES = 8; // At most 8 pieces final int MAXLINES = 8*(MAXPIECES+1); // At most 8 pieces plus a hole, each at most 8 lines long String[] lines = new String[MAXLINES]; int[] startingLine = new int[MAXPIECES+1]; Arrays.fill(startingLine, -1); int numLines = 0; try { while (numLines < MAXLINES) { lines[numLines] = input.readLine(); if (lines[numLines] == null) // after EOF break; ++numLines; } } catch (IOException e) { // do nothing } char lastDescriptor = 'A'; int holeStart = 0; for (int i = 0; i < numLines; ++i) { char c = findNonBlank(lines[i]); if (c == '%') { holeStart = i; break; } else { lastDescriptor = c; if (startingLine[c-'A'] < 0) startingLine[c-'A'] = i; } } int numPieces = lastDescriptor - 'A' + 1; startingLine[numPieces] = holeStart; pieces = new Glass[numPieces]; for (char piece = 'A'; piece <= lastDescriptor; ++piece) { int pieceNum = piece - 'A'; String[] pieceLines = Arrays.copyOfRange(lines, startingLine[pieceNum], startingLine[pieceNum+1]); pieces[pieceNum] = new Glass(pieceLines); } String[] holeLines = Arrays.copyOfRange(lines, holeStart, numLines); window = new Hole(holeLines); } /** * Find the first non-blank character in a string * @param string * @return the first non-blank character or ' ' if all are blank */ private char findNonBlank(String string) { for (int i = 0; i < string.length(); ++i) if (string.charAt(i) != ' ') return string.charAt(i); return ' '; } private void printSolution() { if (solved) System.out.print (window.toString()); else System.out.println ("The window cannot be repaired."); } /** * Attempt to place a piece in the window, then recursively solve the remaining part of the puzzle. * Continue until solved or determined to be unsolvable. * * @param pieceNum piece to place in the window */ private void solve(int pieceNum) { if (pieceNum >= pieces.length) { solved = window.filled(); } else { Glass p = pieces[pieceNum]; // System.err.println ("Attempting to insert\n" + p); tryToInsert (p, pieceNum); if (!solved) { Glass p2 = p.flip(); // System.err.println ("Attempting to insert flipped\n" + p2); tryToInsert (p2, pieceNum); } } } public void tryToInsert (Glass p, int pieceNum) { for (int xoffset = 0; xoffset <= window.getWidth() - p.getWidth() && !solved; ++xoffset) for (int yoffset = 0; yoffset <= window.getHeight() - p.getHeight() && !solved; ++yoffset) if (window.fits(p, xoffset, yoffset)) { window.insert(p, xoffset, yoffset); // System.err.println ("Inserted into window\n" + window); solve (pieceNum+1); if (solved) return; window.remove(p); // System.err.println ("Removed piece from window\n" + window); } } private class GlassCompare implements Comparator<Glass> { @Override public int compare(Glass g1, Glass g2) { return g2.area() - g1.area(); } } /** * Attempt to solve the puzzle. * * @param pieceNum piece to place in the window */ private void solve() { int total = 0; for (int i = 0; i < pieces.length; ++i) total += pieces[i].area(); if (total == window.area()) { // The areas match, so there's at least a possibility that the // glass pieces can fill up the window. // Sort the pieces so that we try the largest ones first - this speeds things // up on average because smaller pieces are more likely to "fit" temporarily into // incorrect positions, which can lead us to explore a lot of dead ends. Arrays.sort(pieces, new GlassCompare()); // Start solving beginning with piece 0 solve(0); } } public static void main (String[] argv) throws FileNotFoundException { BufferedReader inScan = null; if (argv.length > 0) { FileReader infile = new FileReader(argv[0]); inScan = new BufferedReader(infile); } else { inScan = new BufferedReader(new InputStreamReader(System.in)); } try { Reconstructor cw = new Reconstructor(inScan); cw.solve(); cw.printSolution(); } catch (IOException e) { System.err.println ("Input format error: " + e); } } }
Glass.java
/** * */ package StainedGlass; /** * A single piece of stained glass. * * @author zeil * */ public class Glass { private int width; private int height; private char descriptor; private char[][] chars; /** * Initializes a piece of glass given a representation in lines of text. * * For example; given lines == {" W", " WW", " W"}, we would get a Glass piece * with width 2, height 3, and a descriptor of 'W', such that charAt(0,0) == ' ' * and charAt(0,1) == 'W' * * @param text array of strings. Each represents a single line across the glass piece. Blanks indicate * horizontal positions where no glass is present. A letter indicates a position where class of a "color" * denoted by that letter can be found. */ public Glass (String[] text) { width = 0; height = text.length; int leftOffset = Integer.MAX_VALUE; for (int i = 0; i < height; ++i) { for (int w = 0; w < text[i].length(); ++w) { if (text[i].charAt(w) != ' ') { descriptor = text[i].charAt(w); width = Math.max(width, w+1); leftOffset = Math.min(leftOffset, w); } } } width -= leftOffset; chars = new char[height][width]; for (int h = 0; h < height; ++h) { for (int w = leftOffset; w < text[h].length(); ++w) chars[h][w-leftOffset] = text[h].charAt(w); for (int w = text[h].length() - leftOffset; w < width; ++w) chars[h][w] = ' '; } } /** * Returns the character indicating the presence or absence of glass at position * (w,h) in this piece. * * If w or h are out of bounds, returns ' ' (no glass). * * @param x x position (starts at 0, increases moving to the right) * @param y y position (starts at 0, increases moving down the glass) * @return descriptor if glass is present at that location, ' ' otherwise */ public char charAt(int x, int y) { if (y < 0 || y >= height) return ' '; if (x < 0 || x >= width) return ' '; return chars[y][x]; } /** * @return the width */ public int getWidth() { return width; } /** * @return the height */ public int getHeight() { return height; } /** * @return the descriptor character indicating the presence of glass */ public char getDescriptor() { return descriptor; } /** * Produces a new piece of glass by flipping this one around its vertical axis; * E.g., AAA AAA * A becomes A * A A */ public Glass flip() { String[] flippedLines = new String[height]; for (int y = 0; y < height; ++y) { StringBuffer buf = new StringBuffer(); for (int x = width-1; x >= 0; --x) buf.append(chars[y][x]); flippedLines[y] = buf.toString(); } return new Glass(flippedLines); } /** * The area is the total number of positions occupied by colored glass * * @return area of this piece */ public int area() { int total = 0; for (int h = 0; h < height; ++h) for (int w = 0; w < width; ++w) if (chars[h][w] != ' ') ++total; return total; } public String toString() { StringBuffer buf = new StringBuffer(); for (int h = 0; h < height; ++h) { int w = width-1; while (w >= 0 && chars[h][w] == ' ') --w; for (int x = 0; x <= w; ++x) buf.append(chars[h][x]); buf.append('\n'); } return buf.toString(); } public boolean equals (Object o) { try { Glass g = (Glass)o; if (width != g.width || height != g.height || descriptor != g.descriptor) { return false; } for (int h = 0; h < height; ++h) for (int w = 0; w < width; ++w) if (charAt(w,h) != g.charAt(w,h)) return false; return true; } catch (Exception e) { return false; } } }
Hole.java
/** * */ package StainedGlass; public class Hole { private int width; private int height; private char descriptor; private char[][] chars; /** * Initializes a hole given a representation in lines of text. * * For example; given lines == {" %", " %%", " %"}, we would get a Hole * with width 2, height 3, such that charAt(0,0) == ' ' and charAt(0,1) == * '%' * * @param text * array of strings. Each represents a single line across the * glass piece. Blanks indicate horizontal positions where no * glass is present. A '%' indicates a position where glass could * be placed. A letter indicates a position where glass has been * placed. */ public Hole(String[] text) // I probably don't need the descriptor...review // this hunch before submission { width = 0; height = text.length; int leftOffset = Integer.MAX_VALUE; for (int i = 0; i < height; ++i) { for (int w = 0; w < text[i].length(); ++w) { if (text[i].charAt(w) != ' ') { descriptor = text[i].charAt(w); width = Math.max(width, w + 1); leftOffset = Math.min(leftOffset, w); } } } width -= leftOffset; chars = new char[height][width]; for (int h = 0; h < height; ++h) { for (int w = leftOffset; w < text[h].length(); ++w) chars[h][w - leftOffset] = text[h].charAt(w); for (int w = text[h].length() - leftOffset; w < width; ++w) chars[h][w] = ' '; } } /** * Returns the character indicating the presence or absence of glass at * position (w,h) in this piece. * * If w or h are out of bounds, returns ' ' (no glass). * * @param x * x position (starts at 0, increases moving to the right) * @param y * y position (starts at 0, increases moving down the glass) * @return descriptor if glass is present at that location, ' ' otherwise */ public char charAt(int x, int y) { // your code here if (y < 0 || y >= height) return ' '; if (x < 0 || x >= width) return ' '; return chars[y][x]; } /** * @return the width */ public int getWidth() { // your code here return width; } /** * @return the height */ public int getHeight() { // your code here return height; } /** * Determines whether a given piece of glass would fit into the empty spaces * of this hole if the piece were shifted over by (xoffset,yoffset) from the * upper left corner of the hole. * * @param g * a piece of glass * @param xoffset * horizontal offset * @param yoffset * vertical offset * @return true if the glass could be placed in empty spaces in this hole * */ public boolean fits(Glass g, int xoffset, int yoffset) { // your code here try { for (xoffset = 0; xoffset <= width; ++xoffset) for (yoffset = 0; yoffset <= height; ++yoffset) if (g.area() == xoffset) return true; return false; } catch (Exception e) { return false; } } /** * Inserts a piece of glass into the empty spaces of this hole, shifting the * piece over by (xoffset,yoffset) from the upper left corner of the hole. * '%' empty spots in this hole are filled with the descriptor for the * glass. * * Pre-requisite: fits(g, xoffset, yoffset) * * @param g * a piece of glass * @param xoffset * horizontal offset * @param yoffset * vertical offset * */ @SuppressWarnings("null") public void insert(Glass g, int xoffset, int yoffset) { // your code here int[] OS = null; int key; for(xoffset = 1; xoffset <= width; ++xoffset) { key = OS[xoffset]; for (yoffset = 1; yoffset <= height; --yoffset) { OS[yoffset+1] = OS[yoffset]; } OS[yoffset+1] = key; } } /** * Removes a piece of glass previously fitted into this hole, All spaces in * this hole currently occupied by descriptors for g are made empty * (replaced by '%') * * @param g * a piece of glass * @return true if the glass could be placed in empty spaces in this hole * */ public void remove(Glass p) { // your code here p = null; } /** * Is the hole completely filled? * * @return true if all empty spaces have been filled with glass */ public boolean filled() { // your code here try { for (int h = 0; h < height; ++h) for (int w = 0; w < width; ++w) if (charAt(w, h) == ' ') // If position is empty return // false return false; return true; // Otherwise true } catch (Exception e) { return false; // Exception thrown return false } } /** * The area is the total number of positions that are occupied by colored * glass and that are empty and could be so filled. * * @return area of this piece */ public int area() // Mostly the same as Glass.java (just need to account for // empty as well { // your code here int total = 0; for (int h = 0; h < height; ++h) for (int w = 0; w < width; ++w) if (chars[h][w] != ' ' || chars[h][w] == ' ') ++total; return total; } public String toString() // Should be the same as in Glass.java { // your code here StringBuffer buf = new StringBuffer(); for (int h = 0; h < height; ++h) { int w = width - 1; while (w >= 0 && chars[h][w] == ' ') --w; for (int x = 0; x <= w; ++x) buf.append(chars[h][x]); buf.append('\n'); } return buf.toString(); } public boolean equals(Object o) // Should be the same as in Glass.java, just // needed to change Glass // to Hole { // your code here try { Hole g = (Hole) o; if (width != g.width || height != g.height || descriptor != g.descriptor) { return false; } for (int h = 0; h < height; ++h) for (int w = 0; w < width; ++w) if (charAt(w, h) != g.charAt(w, h)) return false; return true; } catch (Exception e) { return false; } } }