Why Longest common string can not recursive first and output latter - java

Here i want to output the longest common string using dynamic programming algorithm ,code below is my implementation.what make me wired is the output A C A D C B, it's obviously wrong, and if i change these two lines and make it print first and recurse latter, result is true.and i have draw such process in paper and really do not know why the first is wrong.
display(flags, c, x-1, y-1);
System.out.print(c[x] + " ");:
public class LCSubstring{
public static void main(String[] args){
String[] x = {"", "A","B","A","D","F","E","C","A"};
String[] y = {"", "B","A","C","A","D","F","C","B","A"};
int[][] flags = getFlag(x, y);
display(flags, x, x.length-1, y.length-1);
}
public static int[][] getFlag(String[] x, String[] y){
int[][] c = new int[x.length][y.length];
int[][] b = new int[x.length][y.length];
for(int i = 1; i < x.length; i++){
for(int j = 1; j < y.length; j++){
if(x[i] == y[j]){
c[i][j] = c[i-1][j-1] + 1;
b[i][j] = 1;
}else if(c[i][j-1] >= c[i-1][j]){
c[i][j] = c[i][j-1];
b[i][j] = 0;
}else{
c[i][j] = c[i-1][j];
b[i][j] = -1;
}
}
}
return b;
}
public static void display(int[][] flags, String[] c, int x, int y){
if (x == 0 || y == 0) {
return;
}
if(flags[x][y] == 1){
display(flags, c, x-1, y-1);
System.out.print(c[x] + " ");
}else if(flags[x][y] == 0){
display(flags, c, x, y-1);
}else if(flags[x][y] == -1){
display(flags, c, x-1, y);
}
}
}
UPDATE:non-recursive in finding result
public static void display(int[][] flags, String[] c, int x, int y){
while (x != 0 && y != 0){
if (flags[x][y] == 1){
System.out.print(c[x] + " ");
x--;
y--;
}else if (flags[x][y] == 0){
y--;
}else if (flags[x][y] == -1){
x--;
}
}
}

When traversing trees (which your code is effectively doing), you can traverse in one of three orders:
pre-order
in-order
post-order
Reference Tree traversal on Wikipedia.
When you change the order of the 2 lines in your code, you are switching between pre-order and in-order traversal. Take a look at the Wikipedia article and it should help you understand the difference between the different traversal orders, and how to code for them.

Related

Can someone help me with controling Snake Game in Java Processing

I am doing a basic Snake Game in Java Processing. It is supposed to turn clockwise whne the user presses L or D, and when the user presses the A or J key the snake should turn counter-clockwise. The keys should not directly control the snake's direction. They should control how the snake turns.
DEMO
Look at DEMO Question 2
QUESTION
image
My Code
final int ROWS=20, COLS=15; //The number of rows and columns of squares
final int SQ_SIZE=40; //The size of each square in pixels
final int[] X_DIRECTIONS = {0, -1, 0, 1}; //X change for down, left, up, right
final int[] Y_DIRECTIONS = {1, 0, -1, 0}; //Y change for down, left, up, right
int startingLength = 5, currentLength = 0, snakeSpeed = 30, currentDirection = 0;
int [] x = new int[ROWS*COLS];
int [] y = new int[ROWS*COLS];
void setup(){
background(#ff9900);
size(600,800); //MUST be COLS*SQ_SIZE, ROWS*SQ_SIZE
resetSnake();
}
void draw(){
if(frameCount % snakeSpeed == 0){
background(#ff9900);
drawCircles(x, y, currentLength, #32CD32);
moveSnake(X_DIRECTIONS[currentDirection], Y_DIRECTIONS[currentDirection]);
//moveSnake(X_DIRECTIONS[currentDirection], 0);
}
}
void resetSnake(){
currentLength = startingLength;
fillArray(y, currentLength, ROWS/2, -1);
fillArray(x, currentLength, COLS/2, 0);
drawCircles(x, y, currentLength, #32CD32);
}
void moveSnake(int addX, int addY){
if(addX != 0){
fillArray(x, currentLength, x[0] + addX, addX);
}
fillArray(y, currentLength, y[0] + addY, -addY);
}
void keyPressed(){
int newDir = keyCode == DOWN ? 0:(keyCode == UP ? 2:(keyCode == RIGHT ? 3:(keyCode == LEFT ? 1:-1)));
if(newDir != -1) currentDirection = newDir;
}
void drawCircles(int[]x, int[]y, int n, int colour){
//Draw circles here
for(int i = 0; i < n; i++){
fill(colour);
circle(x[i]*SQ_SIZE, y[i]*SQ_SIZE, SQ_SIZE);
}
}
void fillArray(int[] a, int n, int start, int delta){
int index = 0;
if(delta > 0){
for(int i = start; i < start + n; i+=delta){
a[index++] = i;
}
}else if(delta < 0){
for(int i = start; i > start-n; i+=delta){
a[index++] = i;
}
}else{
for(int i = 0; i < n; i++){
a[index++] = start;
}
}
}
Since you have the directions in an array, you can "rotate" through them like this:
void keyPressed(){
if (keyCode == 76 //the code for 'l'
|| keyCode == 68) { //the code for 'd'
currentDirection++;
if(currentDirection > 3) { //make sure currentDirection is not bigger than the array length
currentDirection = 0;
}
}
if (keyCode == 65 //the code for 'a'
|| keyCode == 74) { //the code for 'j'
currentDirection--;
if (currentDirection < 0) { //make sure currentDirection is not smaller than 0
currentDirection = 3;
}
}
}

Recursive Longest Common Substring (LCS) problem optmization

I have the following code in Java:
public static int Secret(String a, String b, int x, int y){
if ((x == -1) || (y == -1)) {
return 0;
}
if (a.charAt(x) == b.charAt(y)) {
return Secret(a, b, x-1, y-1) + 1;
} else {
int left = Secret(a, b, x, y-1);
int up = Secret(a, b, x-1, y);
if (left > up) {
return left ;
} else {
return up;
}
}
return -1;
}
This code looks like the Longest Common Substring Problem but with a garbage complexity. I am supposed to opmitize it to O(mn) (space and time).
I tried following the algorithm on the wikipedia (https://en.wikipedia.org/wiki/Longest_common_substring_problem), that is O(mn) (space and time).
public static int iterativeLCS(String a, String b, int x, int y) {
int[][] L = new int[x+1][y+1];
int z = 0;
for (int i = 0; i <= x; i++) {
for (int j = 0; j <= y; j++) {
if (a.charAt(i) == b.charAt(j)) {
if ((i == 0) || (j == 0)) {
L[i][j] = 1;
} else {
L[i][j] = L[i-1][j-1] + 1;
}
if (L[i][j] > z) {
z = L[i][j];
}
} else {
L[i][j] = 0;
}
}
}
}
But the results don't match for some inputs. For example:
xalmandriatico
talcolaritriom
13
13
Expected output (using the recursive alg): 8
Actual output (using the iterative alg from wikipedia): 2
Any idea on what I have to do?

Using Recursion to Solve a Maze in java

I attempted this problem and for some reason its not coming out correct. Given an array of strings, find how many possible solutions exist to the maze where the strings consist of one "R" (the rat), one "C" (the cheese), multiple "X's (blocks that cannot be passed through), and "."'s (possible pathways). The task is to find the number of possible routes the rat can take to get to the cheese without ever increasing the (Euclidean) distance between itself and the cheese at any point on its path. What looks wrong with my code?
public class RatRoute {
private static String[] enc;
private static int count;
private static int[] r;
private static int[] c;
// Test the program
public static void main(String[] args) {
String[] test = {
".R...",
"..X..",
"....X",
"X.X.X",
"...C."};
int num1 = numRoutes(test);
System.out.println(num1);
}
// Set variables, and call recursive function
public static int numRoutes(String[] enc) {
RatRoute.enc = enc;
r = findR(enc);
c = findC(enc);
recursiveHelper(r[0], r[1]);
return count;
}
// Recursive
public static void recursiveHelper(int x, int y) {
/*System.out.println();
System.out.println();
for (int k = 0; k < enc.length; k++) {
System.out.println(enc[k]);
}*/
if(isBlock(x,y)) {
return;
} else if (isBigger(x,y)) {
return;
} else if (isCheese(x, y)) {
count++;
//System.out.println("Found the Cheese! Path number: " + count);
//System.out.println();
return;
}
enc[x] = currentPath(x,y);
recursiveHelper(x + 1, y);
recursiveHelper(x, y + 1);
recursiveHelper(x, y - 1);
recursiveHelper(x - 1, y);
enc[x] = returnPath(x,y);
}
// Change the most recently traveled coordinates into a block
public static String currentPath(int x, int y) {
char[] Chars = enc[x].toCharArray();
Chars[y] = 'X';
String newString = String.valueOf(Chars);
return newString;
}
// Turn path already traveled from blocks back into a usable path to travel (undo the currentPath method)
public static String returnPath(int x, int y) {
char[] Chars = enc[x].toCharArray();
Chars[y] = '.';
String newString = String.valueOf(Chars);
return newString;
}
// Check if the next movement is into the cheese
public static boolean isCheese(int x, int y) {
if (enc[x].charAt(y) == 'C') {
return true;
} else {
return false;
}
}
// Check if the next movement is into a block, or outside the given array
public static boolean isBlock(int x, int y) {
if (x == -1 || y == -1
|| x >= enc.length || y >= enc[x].length()) {
return true;
} else if (enc[x].charAt(y) == 'X') {
//System.out.println(x + "," + y);
return true;
} else {
return false;
}
}
// See if the distance between the rat and the cheese has gotten larger or smaller
public static boolean isBigger(int x, int y) {
double rx = r[0]; double ry = r[1];
double cx = c[0]; double cy = c[1];
double originalDist = Math.sqrt(Math.pow(rx-cx, 2) + Math.pow(ry-cy, 2));
double newDist = Math.sqrt(Math.pow(x-cx, 2) + Math.pow(y-cy, 2));
//System.out.println("Orginal Distance: " + originalDist);
//System.out.println("New Distance: " + newDist);
if (newDist > originalDist) {
return true;
} else {
return false;
}
}
// Find the variables for the original position of the rat
public static int[] findR(String[] enc) {
for (int i = 0; i < enc.length; i++) {
for (int j = 0; j < enc[i].length(); j++) {
if (enc[i].charAt(j) == 'R') {
int[] coordinates = {i, j};
//System.out.println(coordinates[0] + "," + coordinates[1]);
return coordinates;
} else {
}
}
}
int[] other = {-1, -1};
return other;
}
// Find the variables for the original position of the rat
public static int[] findC(String[] enc) {
for (int i = 0; i < enc.length; i++) {
for (int j = 0; j < enc[i].length(); j++) {
if (enc[i].charAt(j) == 'C') {
int[] coordinates = {i, j};
//System.out.println(coordinates[0] + "," + coordinates[1]);
return coordinates;
} else {
}
}
}
int[] other = {-1, -1};
return other;
}
}
Let's start from an useful observation:
[...] without ever increasing the (Euclidean) distance between itself and
the cheese at any point on its path.
Basically what it means is that whenever the rat gets closer to the cheese it never goes back to a farther position.
So let's say the rat x coordinate is 3 and the cheese x coordinate is 5 the rat cannot "go left" (i.e. x = 2) because this would cause it to be farther than before form the cheese.
Because of this, a nice way to simple the problem is to find the directions the rat can go. In your example the rat is up-left from the cheese, so it will only be able to move down or right because otherwise it would get farther from the cheese. When the rat x matches the cheese x it won't be able to move right or left anymore, same goes for the y.
With your code, if:
r[0] - c[0] = 0 // the rat cannot move on the x any more.
r[1] - c[1] = 0 // the rat cannot move on the y any more.
When
r[0] - c[0] == 0 && r[1] - c[1] == 0
The rat reached the cheese! In this case, we can increment the counter because a successful route was found.
Now let's put this in practice with recursion.
From the code you posted, we start with a given c (found with findC(enc)) and a given r (found with findR(enc))
So the recursive method would look like this:
private void findRoutesFrom(int[] r) {
// what directions can the rat go?
// if the cheese is on the right of the mouse, xDirection
// would be +1.
int xDirection = (int) Math.signum(c[0] - r[0]);
// if the cheese is below of the mouse, yDirection
// would be +1.
int yDirection = (int) Math.signum(c[1] - r[1]);
// Now, if xDirection is != 0 the rat can attempt to move
// in that direction, checking if there's not a block
if(xDirection != 0 && !isBlock(r[0] + xDirection, r[1])) {
// if it can move in that direction, then use recursion to
// find all the possible paths form the new position
findRoutesFrom(new int[]{r[0] + xDirection, r[1]});
}
// same goes for yDirection
if(yDirection != 0 && !isBlock(r[0], r[1] + yDirection)) {
findRoutesFrom(new int[]{r[0], r[1] + yDirection});
}
// if the rat reaches the cheese, increase the successful
// paths counter
if(xDirection == 0 && yDirection == 0) {
count++;
}
}
That's it! Because of the Eculedean distance constraint it is enough to check if the directions are != 0 because, when that is false, then the rat cannot move on that direction any more.

replacing a string in an array and keeping it in memory?

so im having problems polishing up my program. this program is supposed to create a 1D array with a user input. then it creates a box of 'O's like this..
N = 4
OOOO
OOOO
OOOO
OOOO
the user inputs coordinates based on the box and the 'O' is changed to an 'X'.
the program is supposed to repeat itself after the coordinates are selected while remembering the position of X and including it in the next loop.
i tried implementing a while loop but it seems that code just loops over the Array without remembering the last position of X.
how could i change the code so it does what i need it to do?
public static void makeArray(int M) {
String input = "";
boolean repeat = false;
int N = InputNumber(input);
String[] Board = new String[N];
M = (int) Math.sqrt(N);
String A = "O";
String B = "X";
System.out.println("Printing " + (M) + " x " + (M) + " board...");
System.out.println("Done.");
System.out.println();
while (!repeat) {
int X = Xvalue(M);
int Y = Yvalue(M);
int C = convertIndex(X, Y, M);
System.out.println("Marking location " + X + "," + Y + ")");
for (int i = 0; i < (Board.length); i++) {
{
Board[i] = A;
if ((i % M == 0)) {
System.out.println();
}
if (i == C) {
Board[i] = Board[i].replace(A, B);
}
if (i == C && C == -1) {
repeat = true;
}
}
System.out.print(Board[i]);
}
System.out.println();
}
}
public static int convertIndex(int x, int y, int N) {
int valX = (x - 1) * N;
int valY = y;
int targetIndex = valX + valY;
return (targetIndex - 1);
}
public static int Xvalue(int M) {
boolean repeat = false;
int X = 0;
while (!repeat) {
System.out.print("Please enter the X-coordinate: ");
String InputX = new Scanner(System.in).nextLine();
X = Integer.parseInt(InputX);
if (X > M) {
System.out.println();
System.out.println("Error, please enter a valid X Coordinate...");
repeat = false;
} else {
repeat = true;
}
}
return X;
}
public static int Yvalue(int M) {
boolean repeat = false;
int Y = 0;
while (!repeat) {
System.out.println();
System.out.print("Please enter the Y-coordinate: ");
String InputY = new Scanner(System.in).nextLine();
Y = Integer.parseInt(InputY);
if (Y > M) {
System.out.println("Error, please enter a valid Y Coordinate...");
repeat = false;
} else {
repeat = true;
}
}
return Y;
}
The trouble with you loop is that it defines every element in you your array before it prints them:
while (!repeat) {
//...
for (int i = 0; i < (Board.length); i++) {
{
Board[i] = A; //Makes each element "O"
//...
if (i == C) { //Makes only the current cooridinate "X"
Board[i] = Board[i].replace(A, B);
}
//...
}
System.out.print(Board[i]);
}
}
To fix it so that old X's are retained, you need to remove assignment Board[i] = A;. But you'll still need to initialize your board, or else you'll have null strings. So you need to add something before the loop like:
String[] Board = new String[N];
M = (int) Math.sqrt(N);
String A = "O";
String B = "X";
//initialize board
for (int i = 0; i < Board.length; i++)
Board[i] = A;
Try using a char[][] instead of a String[]. Then you can just plugin the coordinates the user inputs (e.g. board[x][y] = B). This better represents what you're showing the user as well.
This saves you from having to loop through your String[] and then finding the right character to change. Remember, Strings are immutable, so you'd have to reassign the entire string after replacing the right character. With the char[][] you simply assign 'X' to the right coordinates.
EDIT:
Since a single array is required, you should be able to do the following (instead of looping):
board[x] = board[x].substring(0, y) + A + board[x].substring(y + 1);

Minesweeper program java x and y on 2d array are switched

im creating a code for Minesweeper and trying to implement a GUI. But the problem is that when i run the code and play the game, the position i click on the board reveals the y,x coordinate of that location on the answer board rather than the x, y coordinate. Ive been trying to fix this but i cant see to figure it out. i think it maybe is the way i create the board, but i tried everything i could think of.
class Board{
public MsGUI gui;
private static char[][] userBoard;
private static char[][] solutionBoard;
private static int boundSize = 5;
public Board(){
userBoard = new char[][] {{'-','-','-','-','-'},
{'-','-','-','-','-'},
{'-','-','-','-','-'},
{'-','-','-','-','-'},
{'-','-','-','-','-'}};
solutionBoard = new char[][] {{'0','2','B','2','0'},
{'0','3','B','3','0'},
{'1','3','B','3','1'},
{'B','1','3','B','2'},
{'1','1','2','B','2'}};
return;
}
private static void printBoard(char[][] board){
for (int x = 0; x < boundSize; x++){
for(int y = 0; y < boundSize; y++){
System.out.print(" " + Character.toString(board[x][y]));
}
System.out.println("");
}
System.out.println("");
}
public void flagCell(int xCoordinate, int yCoordinate){
userBoard[xCoordinate][yCoordinate] = 'F';
}
public boolean isFlagged(int xCoordinate,int yCoordinate){
if(userBoard[xCoordinate][yCoordinate] == 'F'){
return true;
}
else{
return false;
}
}
public int getHeight() {
return userBoard.length;
}
public int getWidth(){
return userBoard[0].length;
}
public char getValue(int xCoordinate, int yCoordinate) {
return userBoard[xCoordinate][yCoordinate];
}
private static boolean checkIfAlreadyMarked(int xCoordinate, int yCoordinate)
{
boolean marked = false;
if (Character.toString(userBoard[xCoordinate][yCoordinate]).equals("-") == false)
{
marked = true;
}
return marked;
}
public void revealCell(int xCoordinate, int yCoordinate){
int count = 0;
for(int i = 0;i < userBoard.length;i++){
for(int J = 0;J < userBoard[i].length;J++){
if(userBoard[i][J] != '-'){
count = count + 1;
}
}
if(count == 19){
gui.win("you won");
return;
}
}
if(solutionBoard[xCoordinate][yCoordinate] == 'B'){
userBoard[xCoordinate][yCoordinate] = solutionBoard[xCoordinate][yCoordinate];
gui.lose("You lost. Better luck next time!");
return;
}
if(solutionBoard[xCoordinate][yCoordinate] != '0'){
userBoard[xCoordinate][yCoordinate] = solutionBoard[xCoordinate][yCoordinate];
}else{
userBoard[xCoordinate][yCoordinate] = solutionBoard[xCoordinate][yCoordinate];
for(int i = 1; i > -2; i--){
if(xCoordinate-i >= solutionBoard.length || xCoordinate-i < 0)
continue;
for(int z = 1; z > -2; z--){
if(yCoordinate-z >= solutionBoard[xCoordinate].length || yCoordinate-z < 0)
continue;
else if(userBoard[xCoordinate-i][yCoordinate-z] == 'F' || userBoard[xCoordinate-i][yCoordinate-z] != '-')
continue;
else{
revealCell(xCoordinate-i, yCoordinate-z);
}
}
}
}
}
public void unflagCell(int xCoordinate, int yCoordinate){
userBoard[xCoordinate][yCoordinate]='-';
}
public static void main(String[] args){
Board b = new Board();
b.gui = new MsGUI(b);
b.gui.setVisible(true);
}
}
The way you are initializing the solutionBoard is not what you expect it to be.
If you get solutionBoard[0], you're not accessing the first column(which would be consistent with what I think is your understanding), but the first row(first item of the two-dimensional array): {'0','2','B','2','0'}
So if you want to have x for a row index and y for a column index and still keep this "readable" initialization, you'll have to swap the indices whenever you access the array.
But this will only help you with one problem - human readable array assignment in the beginning, but I think you'll regret this decision in the future.
EDIT:
You can have the array initialized as you want and still use readable format like this:
String readableBoard =
"0 2 B 2 0;" +
"0 3 B 3 0;" +
"1 3 B 3 1;" +
"B 1 B B 2;" +
"1 1 2 B 2";
char[][] board = initBoard(readableBoard);
....
private char[][] initBoard(String readableBoard){
char[][] board = new char[5][5];
String[] rows = readableBoard.split(";");
String[] fields = null;
for (int y = 0; y<rows.length;y++){
fields = rows[y].split(" ");
for (int x = 0; x<fields.length; x++){
board[x][y]=fields[x].charAt(0);
}
}
return board;
}
Now when you call
board[2][0]
You'll get 'B'
If you look at your nested for loops, you're printing off the columns instead of what I assume to be the desired rows. Try switching your for loops to iterate over y, then x.
for (int y = 0; y < boundSize; y++){
for(int x = 0; x < boundSize; x++){
System.out.print(" " + Character.toString(board[x][y]));
}
System.out.println("");
}
System.out.println("");

Categories