Last active
February 11, 2016 07:56
-
-
Save ishmaelmakitla/920632ae6c35805d9aa3 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package za.co.pta.gdg.hashcode.practice; | |
import java.io.FileWriter; | |
import java.io.IOException; | |
import java.util.ArrayList; | |
import java.util.List; | |
/** | |
* This is a utility class for processing Paint Commands | |
* | |
* @author Ishmael Makitla, | |
* GDG-Pretoria-Team-Ish, Hash Code 2016 | |
* | |
*/ | |
public class HashCodeCommandProcessor { | |
private static final char DOT = '.'; | |
private static final char HASH = '#'; | |
//this keeps list of commands that produce the output | |
List<String> commands = new ArrayList<String>(); | |
private char[][] mPictureMatrix; | |
public HashCodeCommandProcessor(char[][] inputMatrix){ | |
this.mPictureMatrix = inputMatrix; | |
} | |
/** | |
* Helper function to process the paint command (update the character-matrix with '.' or '#') | |
* PAINT_SQUARE R C S - paints all cells within the square of (2S + 1) × (2S + 1) dimensions centered at [R , C ] . | |
In particular, the command “PAINT_SQUARE R C 0” paints a single cell [R , C ]: (0+1)x(0+1) = 1 (number of cells) | |
Another example: PAINT_SQUARE 2 3 1 : Centre = [2,3] : ((2x1) +1)((2x1)+1) = (3)x(3) = 9 (number of cells to paint): | |
..###.. | |
..###.. (centre = Row 3 (3-1), Col 4 (4-1)) | |
..###.. | |
* @param paintCommand | |
*/ | |
public void processPaintSquareCommand(int rowIndex, int columnIndex, int s){ | |
int cellNumbers = ((s*2)+1)*((s*2)+1); | |
int cellsPerSide = (int)Math.sqrt((double)cellNumbers)/2; | |
//do the actual painting by changing the characters in the array that are within the specified square | |
if(cellNumbers == 1){ | |
//this is just the printing of one cell - so only one character needs changing | |
mPictureMatrix[rowIndex][columnIndex] = HASH; | |
commands.add("PAINT_SQUARE"+" "+rowIndex+" "+columnIndex+" "+s); | |
} | |
else if (cellsPerSide > 1){ | |
//this is a square bigger than 3x3 | |
commands.add("PAINT_SQUARE"+" "+rowIndex+" "+columnIndex+" "+s); | |
printBigSquare(rowIndex, columnIndex, s); | |
} | |
else{ | |
//the cellNumber has to be indivisible by 2 (otherwise we cannot have a centre) | |
if((cellNumbers%2 == 0)){ | |
System.out.println("Invalid Command for Square Painting ... Number of Cells MUST NOT be divisible by 2. MUST be Odd!! "); | |
return; | |
} | |
//First we paint the centre - easiest | |
mPictureMatrix[rowIndex][columnIndex] = HASH; | |
//here we are painting a number of cells within a square, so we calculate the square-root of the cellNumbers - | |
//we then work out which cells are within the square | |
//we compute the length of each side of the square - by calculating the square-root (this is the number of cells making each side) | |
int sideLength = (int)Math.sqrt((double)cellNumbers); | |
//number of cells on each side of the centre | |
int cellsToTheEdgeOfSquare = sideLength/2; | |
int index = 1; | |
for(int x=0; x < cellsToTheEdgeOfSquare; x++){ | |
//drawing a cross from the center to the four sides | |
//up | |
mPictureMatrix[rowIndex-index][columnIndex] = HASH; | |
//up-and-right | |
mPictureMatrix[rowIndex-index][columnIndex+index] = HASH; | |
//up-and-left | |
mPictureMatrix[rowIndex-index][columnIndex-index] = HASH; | |
//left | |
mPictureMatrix[rowIndex][columnIndex-index] = HASH; | |
//right | |
mPictureMatrix[rowIndex][columnIndex+index] = HASH; | |
//down | |
mPictureMatrix[rowIndex+index][columnIndex] = HASH; | |
//down-and-right | |
mPictureMatrix[rowIndex+index][columnIndex+index] = HASH; | |
//down-and-left | |
mPictureMatrix[rowIndex+index][columnIndex-index] = HASH; | |
index +=1; | |
} | |
//add the command to the command-list | |
//Command-String :: PAINT_SQUARE 5 65 1 | |
commands.add("PAINT_SQUARE"+" "+rowIndex+" "+columnIndex+" "+s); | |
} | |
} | |
/** | |
* For printing square bigger than S=1 | |
*/ | |
private void printBigSquare(int rowIndex, int columnIndex, int s){ | |
//draw lines of length-x starting from top-left corder of the desired square | |
//we compute the length of each side of the square - by calculating the square-root (this is the number of cells making each side) | |
int cellNumbers = ((s*2)+1)*((s*2)+1); | |
int sideLength = (int)Math.sqrt((double)cellNumbers); | |
//sideLength is the length of each line we will draw to make our square | |
//work out the coordinates of the first and last lines | |
//first we need to know how many cells to the edge of the squre | |
int cellsToTheEdgeOfSquare = sideLength/2; | |
int firstColumnIndex = columnIndex - cellsToTheEdgeOfSquare; | |
int lastColumnIndexEnd = columnIndex + cellsToTheEdgeOfSquare+1; //we add 1 to INCLUDE the last column | |
int firstRowIndex = rowIndex - cellsToTheEdgeOfSquare; | |
int lastRowIndex = rowIndex + cellsToTheEdgeOfSquare+1; //we add 1 to INCLUDE the last row | |
//loop from the start-cell of the square to the end, and move to the next row | |
for(int row=firstRowIndex; row < lastRowIndex; row++){ | |
for( int col=firstColumnIndex; col < lastColumnIndexEnd; col++){ | |
mPictureMatrix[row][col] = HASH; | |
} | |
} | |
} | |
/** | |
* PAINT_LINE R1 C1 R2 C2 - paints all cells in a horizontal or vertical run between [R1, C1] (start) and [R2,C2] (end). | |
* That is, at least one of the two has to be true: R1 = R2 or/and C1 = C2 . | |
*/ | |
public void processPaintLineCommand(int startRowIndex, int startColumnIndex, int endRowIndex, int endColumnIndex){ | |
//since this is a line, either same column or same row - otherwise the command is invalid | |
//E.g line on row-0 starts at 0,0 ends at 0,5 (horizontal), or starts at 0,0 ends at 5,0 (vertical) | |
if( (startRowIndex) != endRowIndex && (startColumnIndex != endColumnIndex)){ | |
System.out.println("Invalid Command for Line Painting ... "); | |
return; | |
} | |
boolean isHorizontal = (startRowIndex == endRowIndex ? true : false); | |
//draw the line of length | |
if(isHorizontal){ | |
for(int x= startColumnIndex; x < endColumnIndex+1; x++){ | |
mPictureMatrix[startRowIndex][x] = HASH; | |
} | |
} | |
else{ | |
for(int x= startRowIndex; x < endRowIndex+1; x++){ | |
mPictureMatrix[x][startColumnIndex] = HASH; | |
} | |
} | |
//add the Paint-Line command of the form: PAINT_LINE 0 4 3 4 | |
commands.add("PAINT_LINE"+" "+startRowIndex+" "+startColumnIndex+" "+endRowIndex+" "+endColumnIndex); | |
} | |
/** | |
* Method to process the ERASE command: it basically puts '.' at the specified cell of the 2-D array; | |
* ERASE_CELL R C - clears the cell [R,C]. | |
* | |
*/ | |
public void processEraseCellCommand(int rowIndex, int columnIndex){ | |
mPictureMatrix[rowIndex][columnIndex] = DOT; | |
//add Erase Cell command of the form: ERASE_CELL 8 35 | |
commands.add("ERASE_CELL"+" "+rowIndex+" "+columnIndex); | |
} | |
public String showAsString(){ | |
return asStringPictureMatrix(mPictureMatrix); | |
} | |
/** | |
* Convenience method to create a picture-matrix from dimensions | |
*/ | |
public static char[][] createPictureMatrix(final int rows, final int columns){ | |
char[][] pictureMatrix = new char[rows][columns]; | |
for(int x=0; x< rows; x++){ | |
for (int y=0; y <columns; y++){ | |
pictureMatrix[x][y] = DOT; | |
} | |
} | |
return pictureMatrix; | |
} | |
/** | |
* Convenience method that converts the array onto a matrix-string. It is used to generate the output | |
* similar to those submitted by Google for Hash Code Practice Challenge; | |
* | |
*/ | |
public static String asStringPictureMatrix(final char[][] pictureMatrix){ | |
int rows = pictureMatrix.length; | |
int columns = pictureMatrix[0].length; | |
String outputMatrix = ""; | |
StringBuilder stringBuilder = new StringBuilder(); | |
for(int x=0; x< rows; x++){ | |
for (int y=0; y <columns; y++){ | |
stringBuilder.append(pictureMatrix[x][y]); | |
//end of row? | |
if(y+1 >= columns){ | |
stringBuilder.append('\n'); | |
} | |
} | |
} | |
outputMatrix = stringBuilder.toString(); | |
return outputMatrix; | |
} | |
/** | |
* This function is used to create a file of commands used to produce the desired outcomes | |
*/ | |
public void createCommandsFile(){ | |
try { | |
FileWriter fw = new FileWriter("commands.txt"); | |
fw.write(String.valueOf(commands.size())); | |
fw.write('\n'); | |
for (int x = 0; x < commands.size(); x++) { | |
fw.write(commands.get(x)); | |
//we only add the "return" if this is NOT the last entry | |
if((x+1) < commands.size()) | |
fw.write('\n'); | |
} | |
fw.close(); | |
} catch (IOException e) { | |
// TODO Auto-generated catch block | |
e.printStackTrace(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment