Skip to content

Instantly share code, notes, and snippets.

@ishmaelmakitla
Last active February 11, 2016 07:56
Show Gist options
  • Save ishmaelmakitla/920632ae6c35805d9aa3 to your computer and use it in GitHub Desktop.
Save ishmaelmakitla/920632ae6c35805d9aa3 to your computer and use it in GitHub Desktop.
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