First, sorry for my bad english, especially for programming words, english isnt my first language.
So, i have programmed a software that detect all continuous sprites on an image and list their palettes.
Full explanation of the software here: https://www.vg-resource.com/thread-33373.html
It works alright, however, if the sprite has at least 4300-ish pixels, a stackoverflow exception is thrown.
In order to find the boundaries of every sprite, first i find the first pixel in the sheet that isnt the color of the background. Then, i start my recursive method that verify every adjacent pixels to see if they dont have the background color, then call itself on that position, their position being recorded in a boolean matrix.
The recursive method:
//pixelPosition > the position found of the current sprite, posX/posY > position of the current pixel being examined
public boolean[][] moveToNextPixel(boolean[][] pixelPosition, int posX, int posY)
{
pixelPosition[posX][posY] = true;
//If the next position isnt outside of the boundaries of the image AND if it hasnt already been recorded
// AND if it isnt the color of the background, move to that position.
if(posX + 1 < pixelPosition.length)
{
if(!pixelPosition[posX+1][posY] && !panBackgroundColor.isColorPresentInPalette(workingImage.getRGB(posX+1,posY)) )
{
moveToNextPixel(pixelPosition,posX+1,posY);
}
}
if(posX - 1 >= 0)
{
if(!pixelPosition[posX-1][posY] && !panBackgroundColor.isColorPresentInPalette(workingImage.getRGB(posX-1,posY)))
{
moveToNextPixel(pixelPosition,posX-1,posY);
}
}
if(posY + 1 < pixelPosition[0].length)
{
if(!pixelPosition[posX][posY+1] && !panBackgroundColor.isColorPresentInPalette(workingImage.getRGB(posX,posY+1)))
{
moveToNextPixel(pixelPosition,posX,posY+1);
}
}
if(posY - 1 >= 0)
{
if(!pixelPosition[posX][posY-1] && !panBackgroundColor.isColorPresentInPalette(workingImage.getRGB(posX,posY-1)))
{
moveToNextPixel(pixelPosition,posX,posY-1);
}
}
return pixelPosition;
}
//the method isColorPresentInPalette(int) check if the color in entry is in the background colors
public boolean isColorPresentInPalette( int colorRgb)
{
boolean result = false;
for( int i =0; i< backgroundPalette.length && !result;i++)
{
if(backgroundPalette[i] != null)
{
if(backgroundPalette[i].getRGB() == colorRgb)
{
result = true;
}
}
}
return result;
}
Also, if i load a sheet with normal-sized sprite first, and then load one with a huge sprite (4400+ pixels), it doesnt do the stackoverflow error... So, in the end, im pretty confused on what is the problem exactly.
So, is a recursive method really the right way for this kind of problem? If so what could i do to fix this? Otherwise, anyone see a way to determine each individuals continuous sprites and their positions?
EDITED: Originally I posted a recursive solution but didn't realize that you were doing that. I think after reading more carefully, it seems Recursion might not be the best since you will be adding so many calls given 4300 pixels.
I would just do DFS in memory in this case then. Alternatively, you might try BFS (which will search outwards from the center).
An example of DFS in memory. This basically does the same thing as the recursion above except instead of storing things on the callstack which has a limited buffer size, you would be storing memory:
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Stack;
public class FindNeedleInHaystack {
String[][] haystack;
class Coordinate {
int x;
int y;
public Coordinate(int x, int y) {
this.x = x;
this.y = y;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Coordinate that = (Coordinate) o;
return x == that.x &&
y == that.y;
}
#Override
public int hashCode() {
return Objects.hash(x, y);
}
}
public FindNeedleInHaystack() {
this.haystack = new String[10][10];
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
this.haystack[i][j] = "";
}
}
}
public void addNeedle(int a_x, int a_y) {
this.haystack[a_y][a_x] = "needle";
}
public boolean hasNeedle() {
boolean[][] visited = new boolean[10][10];
return hasNeedleHelper(0, 0);
}
private List<Coordinate> neighbors(Coordinate coord, boolean[][] visited) {
List<Coordinate> neighbors = new ArrayList<>();
int x = coord.x;
int y = coord.y;
if (y + 1 < 10 && !visited[y+1][x]) neighbors.add(new Coordinate(x, y+1));
if (y - 1 >= 0 && !visited[y-1][x]) neighbors.add(new Coordinate(x, y-1));
if (x + 1 < 10 && !visited[y][x+1]) neighbors.add(new Coordinate(x + 1, y));
if (x - 1 >= 0 && !visited[y][x-1]) neighbors.add(new Coordinate(x - 1, y));
return neighbors;
}
private boolean hasNeedleHelper(int x, int y) {
Stack<Coordinate> fringe = new Stack<>();
boolean[][] visited = new boolean[10][10];
fringe.push(new Coordinate(x, y));
while(!fringe.isEmpty()) {
Coordinate toVisit = fringe.pop();
if (this.haystack[toVisit.y][toVisit.x].equals("needle")) {
return true;
} else {
visited[toVisit.y][toVisit.x] = true;
for(Coordinate coord : this.neighbors(toVisit, visited)) {
fringe.push(coord);
}
}
}
return false;
}
public static void main(String...args) {
FindNeedleInHaystack hasNeedle = new FindNeedleInHaystack();
hasNeedle.addNeedle(3, 4);
System.out.println("Has a needle?: " + hasNeedle.hasNeedle());
FindNeedleInHaystack doesntHaveNeedle = new FindNeedleInHaystack();
System.out.println("Has a needle?: " + doesntHaveNeedle.hasNeedle());
}
}
Related
I have a matrix that represents a grid and would like to find out all possible places an object can move to.
An object can only move horizontally or vertically.
Let's assume that the example below is the grid I'm looking at, which is represented as a 2d matrix. The object is the *, the 0s are empty spaces that an object can move to, and the 1s are walls which the object cannot jump over or go on to.
What is the best way to find all possible movements of this object provided that it can only move horizontally or vertically?
I'd like to print a message saying: "There are 9 places the object can go to." The 9 is for the example below, but I would like it to work for any configuration of the below grid. So all I have to do is give the current coordinates of the * and it will give me the number of possible positions it can move to.
A thing to note is that the *'s original position is not considered in the calculations, which is why for the example below the message would print 9 and not 10.
I have a isaWall method that tells me if the cell is a wall or not. The isaWall method is in a Cell class. Each cell is represented by its coordinates. I looked into using Algorithms like BFS or DFS, but I didn't quite understand how to implement them in this case, as I am not too familiar with the algorithms. I thought of using the Cells as nodes of the graph, but wasn't too sure how to traverse the graph because from the examples I saw online of BFS and DFS, you would usually have a destination node and source node (the source being the position of the *), but I don't really have a destination node in this case. I would really appreciate some help.
00111110
01000010
100*1100
10001000
11111000
EDIT: I checked the website that was recommend in the comments and tried to implement my own version. It unfortunately didn't work. I understand that I have to expand the "frontier" and I basically just translated the expansion code to Java, but it still doesn't work. The website continues explaining the process, but in my case, there is no destination cell to go to. I'd really appreciate an example or a clearer explanation pertaining to my case.
EDIT2: I'm still quite confused by it, can someone please help?
While BFS/DFS are commonly used to find connections between a start and end point, that isn't really what they are. BFS/DFS are "graph traversal algorithms," which is a fancy way of saying that they find every point reachable from a start point. DFS (Depth First Search) is easier to implement, so we'll use that for your needs (note: BFS is used when you need to find how far away any point is from the start point, and DFS is used when you only need to go to every point).
I don't know exactly how your data is structured, but I'll assume your map is an array of integers and define some basic functionality (for simplicity's sake I made the start cell 2):
Map.java
import java.awt.*;
public class Map {
public final int width;
public final int height;
private final Cell[][] cells;
private final Move[] moves;
private Point startPoint;
public Map(int[][] mapData) {
this.width = mapData[0].length;
this.height = mapData.length;
cells = new Cell[height][width];
// define valid movements
moves = new Move[]{
new Move(1, 0),
new Move(-1, 0),
new Move(0, 1),
new Move(0, -1)
};
generateCells(mapData);
}
public Point getStartPoint() {
return startPoint;
}
public void setStartPoint(Point p) {
if (!isValidLocation(p)) throw new IllegalArgumentException("Invalid point");
startPoint.setLocation(p);
}
public Cell getStartCell() {
return getCellAtPoint(getStartPoint());
}
public Cell getCellAtPoint(Point p) {
if (!isValidLocation(p)) throw new IllegalArgumentException("Invalid point");
return cells[p.y][p.x];
}
private void generateCells(int[][] mapData) {
boolean foundStart = false;
for (int i = 0; i < mapData.length; i++) {
for (int j = 0; j < mapData[i].length; j++) {
/*
0 = empty space
1 = wall
2 = starting point
*/
if (mapData[i][j] == 2) {
if (foundStart) throw new IllegalArgumentException("Cannot have more than one start position");
foundStart = true;
startPoint = new Point(j, i);
} else if (mapData[i][j] != 0 && mapData[i][j] != 1) {
throw new IllegalArgumentException("Map input data must contain only 0, 1, 2");
}
cells[i][j] = new Cell(j, i, mapData[i][j] == 1);
}
}
if (!foundStart) throw new IllegalArgumentException("No start point in map data");
// Add all cells adjacencies based on up, down, left, right movement
generateAdj();
}
private void generateAdj() {
for (int i = 0; i < cells.length; i++) {
for (int j = 0; j < cells[i].length; j++) {
for (Move move : moves) {
Point p2 = new Point(j + move.getX(), i + move.getY());
if (isValidLocation(p2)) {
cells[i][j].addAdjCell(cells[p2.y][p2.x]);
}
}
}
}
}
private boolean isValidLocation(Point p) {
if (p == null) throw new IllegalArgumentException("Point cannot be null");
return (p.x >= 0 && p.y >= 0) && (p.y < cells.length && p.x < cells[p.y].length);
}
private class Move {
private int x;
private int y;
public Move(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
}
Cell.java
import java.util.LinkedList;
public class Cell {
public final int x;
public final int y;
public final boolean isWall;
private final LinkedList<Cell> adjCells;
public Cell(int x, int y, boolean isWall) {
if (x < 0 || y < 0) throw new IllegalArgumentException("x, y must be greater than 0");
this.x = x;
this.y = y;
this.isWall = isWall;
adjCells = new LinkedList<>();
}
public void addAdjCell(Cell c) {
if (c == null) throw new IllegalArgumentException("Cell cannot be null");
adjCells.add(c);
}
public LinkedList<Cell> getAdjCells() {
return adjCells;
}
}
Now to write our DFS function. A DFS recursively touches every reachable cell once with the following steps:
Mark current cell as visited
Loop through each adjacent cell
If the cell has not already been visited, DFS that cell, and add the number of cells adjacent to that cell to the current tally
Return the number of cells adjacent to the current cell + 1
You can see a visualization of this here. With all the helper functionality we wrote already, this is pretty simple:
MapHelper.java
class MapHelper {
public static int countReachableCells(Map map) {
if (map == null) throw new IllegalArgumentException("Arguments cannot be null");
boolean[][] visited = new boolean[map.height][map.width];
// subtract one to exclude starting point
return dfs(map.getStartCell(), visited) - 1;
}
private static int dfs(Cell currentCell, boolean[][] visited) {
visited[currentCell.y][currentCell.x] = true;
int touchedCells = 0;
for (Cell adjCell : currentCell.getAdjCells()) {
if (!adjCell.isWall && !visited[adjCell.y][adjCell.x]) {
touchedCells += dfs(adjCell, visited);
}
}
return ++touchedCells;
}
}
And that's it! Let me know if you need any explanations about the code.
I'm seeing a strange behaviour in a coding puzzle I was working on 'Knights Path'. I generate the set of possible moves and store these in a HashSet (the Move class simply has an x,y co-ordinates and a standard hashcode and equals). When I use a HashSet in the generateMoves() method the program doesn't find a solution whereas when I change to the LinkedHashSet it does.
public static Collection<Move> generateMoves(int startX, int startY){
Set<Move> moves = new HashSet<Move>(); <-- doesn't work
public static Collection<Move> generateMoves(int startX, int startY){
Set<Move> moves = new LinkedHashSet<Move>(); <-- works
I know that HashSet doesn't provide any guarantees on the ordering of the iterator elements but the ordering of the moves should not matter in terms of the eventual finding of a solution using backtracking method (some ordering of moves would be more optimal than others but with this brute force approach eventually all paths should be considered).
Clearly there is something funky going on with the iterator of the Collection from HashSet but I have conducted multiple tests to compare the output of the generateMoves for every board position using a LinkedHashSet and a HashSet and they are the same.
Full code below, any pointers greatly appreciated as I'm very curious to understand what may be going on here!
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
public class KnightTour {
private static int countSteps = 0;
public static void main(String[] args){
int[][] board = new int[8][8];
board[0][0] = 1;
solveTour(board,0,0,1);
}
public static class Move{
#Override
public String toString() {
return "["+ x + "," + y + "]";
}
int x;
int y;
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Move other = (Move) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}
}
private static void printBoard(int[][] board){
System.out.println("---------");
for(int i=0;i <8;i++){
for(int j=0; j<8; j++){
if(board[i][j] != 0){
System.out.print('x');
}else{
System.out.print('0');
}
}
System.out.println('\r');
}
System.out.println("---------");
}
public static boolean solveTour(int[][] sol, int x, int y, int movei){
countSteps++;
if(countSteps%100000 == 0){
System.out.println("Count:"+countSteps);
}
Collection<Move> moves = generateMoves(x,y);
if(movei == 64){
printBoard(sol);
return true;
}
for(Move tryMove : moves){
int next_x = tryMove.x;
int next_y = tryMove.y;
if(isValidMove(sol, next_x,next_y)){
sol[next_x][next_y] = movei;
if(solveTour(sol, next_x, next_y, movei+1)){
return true;
}else{
sol[next_x][next_y] = 0;
}
}
}
return false;
}
public static boolean isValidMove(int[][] board, int destX, int destY){
if(destX < 0 || destX > 7 || destY < 0 || destY > 7){
return false;//Off the board!
}
return board[destX][destY] == 0;
}
public static Collection<Move> generateMoves(int startX, int startY){
Set<Move> moves = new HashSet<Move>();//Doesn't terminate
// Set<Move> moves = new LinkedHashSet<Move>();//Works with Linked
for(int i=-2; i<=2; i++){
for(int j=-2; j<=2; j++){
if(Math.abs(i) == Math.abs(j) || i == 0 || j==0 ){
//no op
}else{
Move m = new Move();
m.x = startX + i;
m.y = startY + j;
moves.add(m);
}
}
}
return moves;
}
}
It looks to me like what you might be seeing is a side effect of LinkedHashMap iteration, which guarantees to iterate in the order of insert. HashSet does not have this same guarantee and can return the results in any order.
I think that the ordering of moves is probably important to your algorithm and perhaps an accidental heuristic you are applying by traversing in that order. The random ordering of moves may increase the complexity and introduce many new and suboptimal routes to explore recursively.
The HashSet solution might complete, it might be interesting to try with a small board and see if you get a result from that.
For my programming course I have to write recursive functions, but aside from the theoretical questions given during the classes I can't figure out how to do it with my own code.
If anyone could help me out and give me a pointer on where to start it'd be great!
The method is as follows:
public boolean hasColumn(Marble m) {
boolean hasColumn = false;
for (int i = 0; i < DIM && hasColumn == false; i++) {
int winCount = 0;
for (int j = 0; j < DIM && hasColumn == false; j++) {
if (j == 0) {
winCount = 1;
} else {
if (getField(j, i).equals(getField(j - 1, i))
&& getField(j, i).equals(m)) {
winCount++;
if (winCount == WINLENGTH) {
hasColumn = true;
}
} else {
winCount = 1;
}
}
if (!(getField(j, i).equals(m))) {
hasColumn = false;
}
}
}
return hasColumn;
}
There's a field[DIM][DIM], which stores Marbles. Marble has a Mark, which is 0-4, with 0 being empty and 1-4 being colour values. The method determines whether someone has a marble column of 5 and wins.
Input is the Marble type of a player. Output is boolean hasColumn true or false. The output value is correct, there's just no recursion.
The idea is to make it find a vertical column in a recursive way. This also has to be done with horizontal/vertical, but I figured when I get this figured out I'll manage those by myself.
Thank you in advance!
public boolean hasColumn(Marble m, int i, int j, int wincount) {
if (wincount == WINLENGTH)
return true;
if (i == DIM)
return false;
if (j == DIM)
return hasColumn(m, i + 1, 0, 0);
return hasColumn(m, i, j + 1, getField(j, i).equals(m) ? wincount + 1 : 0);
}
Depending on whether you'd like to find a line/column of elements equal to a given Marble element or rather of same value, you may call this method:
hasColumn(aMarble, 0, 0, 0);
hasColumn(getField(0, 0), 0, 0, 0);
There's a duality between certain types of recursion and iteration.
Consider that in your iterative function you are iteratinng over columns using two variables, i and j. Could you transform those local variables into parameters to the function? You would be transforming state internal to the function (local variables) into state implicit in the function call.
Looks like task sounds like:
1. We have a square matrix of Marble elements(it can be simple integers) with dimension DIM.
2. We have a method getField(int, int) return a marble from this matrix
3. We have an iterative decision to discover if this matrix has any column with equal values of marble elements
Our goal is write recursive variant of this method
So, look here. Recursive algorithm check ROW existing with same value:
public class Marble {
public static final int DIM = 10;
public int[][] marbleAr = new int[DIM][DIM];
public void init(){
for(int i=0;i<DIM;i++){
for(int j=0;j<DIM;j++){
marbleAr[i][j] = new Random().nextInt(10);
if(i == 2){
marbleAr[i][j] = 7;
}
}
}
}
public int get(int i, int j){
return marbleAr[i][j];
}
public void printMarbleAr(){
for(int i=0;i<DIM;i++){
for(int j=0;j<DIM;j++){
System.out.print(marbleAr[i][j] + " ");
}
System.out.println();
}
}
public boolean hasColumn(int val, int col, int row){
if(row == 0){
return true;
}
if(this.hasColumn(val, col, row-1)){
if(this.get(col, row) == this.get(col,row-1)){
return true;
}else{
if(col == DIM-1){
return false;
}
return this.hasColumn(val, col+1, row);
}
}
return false;
}
public static void main(String[] args) {
int v = 7;
Marble marble = new Marble();
marble.init();
marble.printMarbleAr();
System.out.println(marble.hasColumn(v, 0, DIM-1));
}
}
Your method name is hasColumn and return variable
name is hasColumn. That's BAD.
I don't see hasColumn invoked inside the method again to actually
go down to recursion path.
i am currently working on this for personal gratification and would like some advice on how i can make this code faster :
I have one ArrayList composed of an object note, which have coordinates and color value stored in it.
Each "note" is created in real time during the rendering call.
I have made this function :
void keyPressed() {
if (key == 's' || key == 'S') {
PImage img = createImage(posX, specSize, RGB);
for(int x = 0; x < posX; x++){
for(int y = 0; y < specSize; y++){
for(int i = 0; i < notes.size(); i++){
if( (notes.get(i).getX() == x)
&& (notes.get(i).getY() == y) ){
int loc = x + y*posX;
img.pixels[loc] = color(notes.get(i).getR(),
notes.get(i).getG(), notes.get(i).getB());
}
}
}
}
img.updatePixels();
img.save("outputImage.png");
}
}
So when i press the "S" key, i run a loop on the width and height because they can be different in each run, and then on my arrayList and get the corresponding "note" with it's x and y position.
then i write my picture file.
As you can imagine, this is really, really, slow...
Around 5 to 6 minutes for a 1976x256px file.
For me it's okay but it would be great to shorten this a little.
Is there a way to optimize this three loops?
If you need more code, please let me know it's a small code and i don't mind.
How about this?
void keyPressed() {
if (key == 's' || key == 'S') {
PImage img = createImage(posX, specSize, RGB);
for(int i = 0; i < notes.size(); i++){
int x = notes.get(i).getX();
int y = notes.get(i).getY();
int loc = x + y*posX;
img.pixels[loc] = color(notes.get(i).getR(),
notes.get(i).getG(), notes.get(i).getB());
}
img.updatePixels();
img.save("outputImage.png");
}
}
Update:
Not sure what the type of notes is, but something like this might work too. Insert the correct type for one element of Notes into the for loop where I wrote ???.
void keyPressed() {
if (key == 's' || key == 'S') {
PImage img = createImage(posX, specSize, RGB);
for(??? note : notes ){
int x = note.getX();
int y = note.getY();
int loc = x + y * posX;
img.pixels[loc] = color(note.getR(), note.getG(), note.getB());
}
img.updatePixels();
img.save("outputImage.png");
}
}
Can clone notes (and any other object that is used to save) and do this in a different thread so its async to UI. the code will take same or more time but the user can use the rest of the app. Clone is neccesary as you want a snap shot of state when save was clicked.
Dont make a thread put use a ThreadPoolExecutor with one thread max. In the run method could apply what David suggested - one loop instead of two.
Convert your list of notes into a structure mapped like
Map<Integer, Map<Integer, Note> noteMap
Then replace your inner-most loop with a single call like
yNoteMap = note.get(x);
if (yNoteMap != null) {
note = yNoteMap.get(y);
if (note != null) {
// do stuff with note
}
}
Your computational complexity will go from about O(n^3) to O(n^2).
Create a class such as Point with two properties of x and y and implement proper equals and hashcode methods as:
public class Point {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Point point = (Point) o;
if (x != point.x)
return false;
if (y != point.y)
return false;
return true;
}
#Override
public int hashCode() {
int result = x;
result = 31 * result + y;
return result;
}
}
now put the Point as key of a map, and find your points using this, so you don't have to iterate over the whole lists.
I have a problem I am trying to do to practice, and I'm having trouble figuring out how to write a recursive algorithm for it. I have a file that is laid out like so:
4
(())
()((
(()(
))))
This problem is from USACO. http://www.usaco.org/index.php?page=viewproblem2&cpid=189
The problem statement is copy-pasted below:
Although Bessie the cow finds every string of balanced parentheses to
be aesthetically pleasing, she particularly enjoys strings that she
calls "perfectly" balanced -- consisting of a string of ('s followed
by a string of )'s having the same length. For example:
(((())))
While walking through the barn one day, Bessie discovers an N x N grid
of horseshoes on the ground, where each horseshoe is oriented so that
it looks like either ( or ). Starting from the upper-left corner of
this grid, Bessie wants to walk around picking up horseshoes so that
the string she picks up is perfectly balanced. Please help her
compute the length of the longest perfectly-balanced string she can
obtain.
In each step, Bessie can move up, down, left, or right. She can only
move onto a grid location containing a horseshoe, and when she does
this, she picks up the horseshoe so that she can no longer move back
to the same location (since it now lacks a horseshoe). She starts by
picking up the horseshoe in the upper-left corner of the grid. Bessie
only picks up a series of horseshoes that forms a perfectly balanced
string, and she may therefore not be able to pick up all the
horseshoes in the grid.
I am having issues trying to figure out how I would create an algorithm that found the best possible path recursively. Can anyone point me in the right direction, or have any examples I could look at to get an idea? I've been searching but all examples I've found are from one point to another, and not finding all possible paths within a matrix/array.
package bessiehorseshoe;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class BessieHorseShoe {
int answer = 0;
int matrixSize = 0;
public static void main(String[] args) throws IOException {
BessieHorseShoe goBessieGo = new BessieHorseShoe();
}
BessieHorseShoe() throws IOException {
int rowFilled = 0;
int currentColumn = 0;
int character = 0;
BufferedReader inputFile = new BufferedReader(new FileReader("hshoe.in"));
String inputLine = inputFile.readLine();
matrixSize = Character.digit(inputLine.charAt(0), 10);
System.out.println(matrixSize);
char[][] pMatrix = new char[matrixSize][matrixSize];
while ((character = inputFile.read()) != -1) {
char c = (char) character;
if (c == '(' || c == ')') {
pMatrix[rowFilled][currentColumn] = c;
System.out.print(pMatrix[rowFilled][currentColumn]);
rowFilled++;
if (rowFilled == matrixSize) {
currentColumn++;
rowFilled = 0;
System.out.println();
}
}
}
matchHorseShoes(pMatrix);
}
public int matchHorseShoes(char[][] pMatrix) {
if (pMatrix[0][0] == ')') {
System.out.println("Pattern starts with ')'. No possible path!");
return 0;
}
System.out.println("Works");
return 0;
}
}
The following algorithm will solve your problem. You can also use memoization to speed up the running time.
The idea is simple:
while opening parentheses increment the count of opened parentheses;
if you star closing, you must continue to close and increment the closed parentheses;
if you are closing and the number of closed parentheses are greater or equal to the number of opened parentheses, stop and return this value.
All the rest of the code is syntactic sugar. (From the returned list of items visited is trivial obtail the output you desire).
import java.util.LinkedList;
import java.util.List;
public class USACO {
static class Path {
public List<String> items;
public int value;
public Path() {
this.items = new LinkedList<String>();
this.value = 0;
}
}
public static void main(final String[] args) {
final int n = 5;
final String[][] input = new String[n][n];
// Create a random input of size n
for (int y = 0; y < n; y++) {
for (int x = 0; x < n; x++) {
input[y][x] = Math.random() < 0.5 ? "(" : ")";
System.out.print(input[y][x] + " ");
}
System.out.println();
}
final Path bestPath = longestPath(n, input, 0, 0, 0, 0, input[0][0] == "(");
System.out.println("Max:" + bestPath.value + "\n" + bestPath.items);
}
public static Path longestPath(final int n, final String[][] input, final int x, final int y, int numberOpened, int numberClosed,
final boolean wasOpening) {
if (input == null) {
return new Path();
} else if (!wasOpening && (numberClosed >= numberOpened)) { // Reached a solution
final Path path = new Path();
path.value = numberOpened;
path.items.add("(" + x + "," + y + ")");
return path;
} else if ((x < 0) || (y < 0) || (x >= n) || (y >= n)) { // Out of bound
return new Path();
} else if (input[y][x] == "") { // Already visited this item
return new Path();
} else {
final String parenthese = input[y][x];
// Increment the number of consecutive opened or closed visited
if (parenthese.equals("(")) {
numberOpened++;
} else {
numberClosed++;
}
input[y][x] = ""; // Mark as visited
Path bestPath = new Path();
bestPath.value = Integer.MIN_VALUE;
// Explore the other items
for (int dy = -1; dy <= 1; dy++) {
for (int dx = -1; dx <= 1; dx++) {
if (((dy == 0) || (dx == 0)) && (dy != dx)) { // go only up, down, left, right
final boolean opening = (parenthese == "(");
if (wasOpening || !opening) {
// Find the longest among all the near items
final Path possiblePath = longestPath(n, input, x + dx, y + dy, numberOpened, numberClosed, opening);
if (possiblePath.value > bestPath.value) {
bestPath = possiblePath;
bestPath.items.add("(" + x + "," + y + ")");
}
}
}
}
}
input[y][x] = parenthese; // mark as not visited
return bestPath;
}
}
}