Related
The goal of this project is to create a class search. I will need methods of binary search and linear search. For each method you are going to ask the user for a key, then search for this key in an array of numbers (you can assume the numbers in the array). If you found the key return its location, otherwise returns -1. Test these methods by creating an object from the Search class (in the main method) and calling the linear and the binary methods.
Below I have created the code and I am trying to create my main so I can test the linear and binary methods but it is not working. It could be because I'm testing like three different classes in the same main, but I am not sure I formatted them in the right way and that's the reason why I am getting errors. I need help, please.
My Search class.
`
public class Search {
public static int linearsearch(int arr2[], int x2) {
int N = arr2.length;
for (int i = 0; i < N; i++) {
if (arr2[i] == x2)
return i;
}
return -1;
}
public int binarySearch(int arr3[], int l, int r, int x) {
if (r >= l) {
int mid = l + (r-1)/2;
if (arr3[mid] ==x)
return mid;
if(arr3[mid] > x)
return binarySearch(arr3, l, mid -1, x);
return binarySearch(arr3, mid + 1, r, x);
}
return -1;
}
}
My Main class
public class MainTester {
public static void main(String args[]) {
//sorting tester
Sorting obj = new Sorting();
int arr[] = {9,5,4,1,6,10,3,2,7,8};
obj.bubbleSort(arr);
System.out.println("Sorted array:");
obj.printArray(arr);
//binary search tester
int arr3[] = {2,3,5,4,30};
int n = arr3.length;
int x = 10;
int result = binarySearch(arr3, 0, n-1, x);
if (result == -1)
System.out.println("Element not present");
else System.out.println("Element found " + result);
//linear search tester
int arr2[] = {2,3,4,10,30};
int x2 = 10;
int result2 = linearsearch(arr2, x2);
if (result2 == -1)
System.out.print("Element is not present in array.");
else
System.out.print("Element is present " +result2);
}
private static int binarySearch(int[] arr3, int l, int r, int x) {
// TODO Auto-generated method stub
return -1;
}
private static int linearsearch(int[] arr2, int x) {
// TODO Auto-generated method stub
return -1;
}
}
I was expecting this code to test all my methods in the main so I can print the result of my binary and linear search
Here is a working version of your code.
There was still some mistakes. See comments in code below.
Class 'Search'
//Don't mix static and non static method
public class Search {
//linearsearch replaced by linearSearch: use camel case in your class and method names
//Try to use variable names that will help to understand your code.
//Here 'x' has been replaced by 'numberToFind'
public int linearSearch(int arr[], int numberToFind) {
int n = arr.length;//N replaced by n: use Java coding convention
for (int i = 0; i < n; i++) {
if (arr[i] == numberToFind)
return i;
}
return -1;
}
public int binarySearch(int arr[], int l, int r, int numberToFind) {
if (r >= l) {
// There was an error at line below when calculating the 'mid' number
// int mid = l + (r - 1) / 2;
int mid = (l + r) / 2;
if (arr[mid] == numberToFind)
return mid;
if (arr[mid] > numberToFind)
return binarySearch(arr, l, mid - 1, numberToFind);
return binarySearch(arr, mid + 1, r, numberToFind);
}
return -1;
}
}
Class 'MainTester'
Try to avoid repetitive code.
If you have some, extract it to another method and call that method.
public class MainTester {
private Search search;
public MainTester() {
super();
search = new Search();
}
public void testLinearSearch(int[] numberArray, int numberToFind) {
int result = search.linearSearch(numberArray, numberToFind);
printResult("Linear search: ", numberToFind, result);
}
public void testBinarySearch(int[] arr, int numberToFind) {
int result = search.binarySearch(arr, 0, arr.length - 1, numberToFind);
printResult("Binary search: ", numberToFind, result);
}
private void printResult(String searchType, int searchNumber, int arrayIndex) {
if (arrayIndex == -1)
System.out.println(searchType + "Element " + searchNumber + " is not present in array.");
else
System.out.println(searchType + "Element " + searchNumber + " is present at index " + arrayIndex);
}
public static void main(String args[]) {
MainTester tester = new MainTester();
// Try to find a number using linear search
int numbertoFind = 10;
int[] arr2 = { 2, 3, 4, 10, 30 };
tester.testLinearSearch(arr2, 10);
// Try to find a number using binary search with an unsorted array: will not
// work
numbertoFind = 4;
int[] unsortedArray = { 2, 3, 5, 4, 30 };
tester.testBinarySearch(unsortedArray, numbertoFind);
// Try to find a number using binary search with an sorted array: works
int sortedArray[] = { 2, 3, 4, 5, 30 };
tester.testBinarySearch(sortedArray, numbertoFind);
}
}
Hope it helps.
I'm creating a 2d top down game where the enemy AI is constantly following the player and avoiding obstacles. I did some research about path-finding algorithms and I decided to implement the breadth first search, but for some reason, the xy coordinates of the path are reversed, even though the grid is correct.
Code:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class BFSTest {
// 1 = normal node
// 0 = obstacle
// S = start
// D = destination
private static char[][] nodes = {
{'S', '1', '1', '1'},
{'0', '0', '0', '1'},
{'0', '0', '0', '1'},
{'1', '1', '1', 'D'}
};
public static void main(String[] args) {
shortestPath();
}
public static List<Node> shortestPath() {
// key node, value parent
Map<Node, Node> parents = new HashMap<Node, Node>();
Node start = null;
Node end = null;
// find the start node
for (int row = 0; row < nodes.length; row++) {
for (int column = 0; column < nodes[row].length; column++) {
if (nodes[row][column] == 'S') {
start = new Node(row, column, nodes[row][column]);
break;
}
}
}
if (start == null) {
throw new RuntimeException("can't find start node");
}
// traverse every node using breadth first search until reaching the destination
List<Node> temp = new ArrayList<Node>();
temp.add(start);
parents.put(start, null);
boolean reachDestination = false;
while (temp.size() > 0 && !reachDestination) {
Node currentNode = temp.remove(0);
List<Node> children = getChildren(currentNode);
for (Node child : children) {
// Node can only be visited once
if (!parents.containsKey(child)) {
parents.put(child, currentNode);
char value = child.getValue();
if (value == '1') {
temp.add(child);
} else if (value == 'D') {
temp.add(child);
reachDestination = true;
end = child;
break;
}
}
}
}
if (end == null) {
throw new RuntimeException("can't find end node");
}
// get the shortest path
Node node = end;
List<Node> path = new ArrayList<Node>();
while (node != null) {
path.add(0, node);
node = parents.get(node);
}
printPath(path);
return path;
}
private static List<Node> getChildren(Node parent) {
List<Node> children = new ArrayList<Node>();
int x = parent.getX();
int y = parent.getY();
if (x - 1 >= 0) {
Node child = new Node(x - 1, y, nodes[x - 1][y]);
children.add(child);
}
if (y - 1 >= 0) {
Node child = new Node(x, y - 1, nodes[x][y - 1]);
children.add(child);
}
if (x + 1 < nodes.length) {
Node child = new Node(x + 1, y, nodes[x + 1][y]);
children.add(child);
}
if (y + 1 < nodes[0].length) {
Node child = new Node(x, y + 1, nodes[x][y + 1]);
children.add(child);
}
return children;
}
private static void printPath(List<Node> path) {
for (int row = 0; row < nodes.length; row++) {
for (int column = 0; column < nodes[row].length; column++) {
String value = nodes[row][column] + "";
// mark path with X
for (int i = 1; i < path.size() - 1; i++) {
Node node = path.get(i);
if (node.getX() == row && node.getY() == column) {
value = "X";
break;
}
}
if (column == nodes[row].length - 1) {
System.out.println(value);
} else {
System.out.print(value + " ");
}
}
}
System.out.println("Path: " + path);
}
}
class Node {
private int x;
private int y;
private char value;
public Node(int x, int y, char value) {
this.x = x;
this.y = y;
this.value = value;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public char getValue() {
return value;
}
#Override
public String toString() {
return "(x: " + x + " y: " + y + ")";
}
#Override
public int hashCode() {
return x * y;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null) return false;
if (this.getClass() != o.getClass()) return false;
Node node = (Node) o;
return x == node.x && y == node.y;
}
/* Output:
* S X X X
* 0 0 0 X
* 0 0 0 X
* 1 1 1 D
* Path: [(x: 0 y: 0), (x: 0 y: 1), (x: 0 y: 2), (x: 0 y: 3), (x: 1 y: 3), (x: 2 y: 3), (x: 3 y: 3)]
*/
}
Thanks!
Think about this for a moment. Remember that your first array index is row, and the second is column. Now, in terms of conventional x and y:
the y index always refers to the row (because you count rows vertically);
the x index always refers to the column (because you count columns horizontally).
So, the correct way to index your grid is nodes[y][x]
I'm just beginner in programming.
uf is a union-find class with the method union which connects the roots of two node.
This piece of code is responsible for opening a site of a grid and union the site with its neighbor if any of neighbor is opened. And if one of its neighbors is full, then fill all nodes that connected with the site.
This is the actual code:
if(i == 1){
uf.union(len*len, xyTo1D(i,j));
if(existAndOpen(i+1,j)){
uf2.union(xyTo1D(i+1,j), xyTo1D(i,j));
uf.union(xyTo1D(i,j), xyTo1D(i+1,j));
}
if(existAndOpen(i-1,j)){
uf2.union(xyTo1D(i-1,j), xyTo1D(i,j));
uf.union(xyTo1D(i,j), xyTo1D(i-1,j));
}
if(existAndOpen(i,j-1)){
uf2.union(xyTo1D(i,j-1), xyTo1D(i,j));
uf.union(xyTo1D(i,j), xyTo1D(i,j-1));
}
if(!(j == len && i == len)){
if(existAndOpen(i,j+1)){
uf2.union(xyTo1D(i,j+1), xyTo1D(i,j));
uf.union(xyTo1D(i,j), xyTo1D(i,j+1));
}
}
}
else{
if(existAndFull(i+1,j)){
uf2.union(xyTo1D(i+1,j), xyTo1D(i,j));
uf.union(xyTo1D(i,j), xyTo1D(i+1,j));
}
if(existAndFull(i-1,j)){
uf2.union(xyTo1D(i-1,j), xyTo1D(i,j));
uf.union(xyTo1D(i,j), xyTo1D(i-1,j));
}
if(existAndFull(i,j-1)){
uf2.union(xyTo1D(i,j-1), xyTo1D(i,j));
uf.union(xyTo1D(i,j), xyTo1D(i,j-1));
}
if(!(j== len && i == len)){
if(existAndFull(i,j+1)){
uf2.union(xyTo1D(i,j+1), xyTo1D(i,j));
uf.union(xyTo1D(i,j), xyTo1D(i,j+1));
}
}
if(existAndOpen(i+1,j)){
uf.union(xyTo1D(i,j), xyTo1D(i+1,j));
}
if(existAndOpen(i-1,j)){
uf.union(xyTo1D(i,j), xyTo1D(i-1,j));
}
if(existAndOpen(i,j-1)){
uf.union(xyTo1D(i,j), xyTo1D(i,j-1));
}
if(!(j== len && i == len)){
if(existAndOpen(i,j+1)){
uf.union(xyTo1D(i,j), xyTo1D(i,j+1));
}
}
}
}
How can I simplify the code?
Try this
boolean f1(int a, int b) { }
boolean f2(int a, int b) { }
void A(int a, int b) { }
void testAndA(BiPredicate<Integer, Integer> p, int a, int b) {
if (p.test(a, b))
A(a, b);
}
and
if(x == 1){
testAndA(this::f1, x + 1, y);
testAndA(this::f1, x, y + 1);
} else {
testAndA(this::f2, x + 1, y);
testAndA(this::f2, x, y + 1);
}
You can write a loop to loop through all of the different values that could be passed to f1(), such as something like:
for (int deltax = -1; deltax <= 1; deltax++) {
for (int deltay = -1; deltay <= 1; deltay++) {
if (f1(x + deltax, y + deltay)) {
A(x + deltax, y + deltay);
}
}
}
Of course change the start and end values of deltax and deltay depending on which conditions you need to check.
You say there are "more if statements in each block." Reading between the lines, I assume that means you need to make more calls to f1/f2 and A, but with different x and y offsets.
Here is a program that shows a way to refactor the code to avoid coding repetition. Its main features are:
It uses object orientation to abstract the inner if blocks.
It uses an offsets array to represent the x/y offsets for each inner if block.
The doIt() method uses a loop to invoke the inner if blocks.
public class Main {
static interface F {
void f(int i, int j);
}
static class F1Caller implements F {
public void f(int a, int b) {
if (f1(a, b)) {
A(a, b);
}
}
}
static class F2Caller implements F {
public void f(int a, int b) {
if (f2(a, b)) {
A(a, b);
}
}
}
static boolean f1(int a, int b) { System.out.print(" f1. "); return true; }
static boolean f2(int a, int b) { System.out.print(" f2. "); return true; }
static void A(int a, int b) { System.out.println("a: " + a + ", b: " + b); }
static F1Caller f1Caller = new F1Caller();
static F2Caller f2Caller = new F2Caller();
// x and y offsets for each call to f1/f2.
// Add more offset rows, as needed.
static int offsets[][] = {
{1, 0},
{0, -1}
};
static void doIt(int x, int y) {
System.out.println("x: " + x + ", y: " + y);
F f = (x == 1) ? f1Caller : f2Caller;
for (int k = 0; k < offsets.length; k++) {
f.f(x + offsets[k][0], y + offsets[k][1]);
}
}
public static void main(String[] args) {
doIt(0, 0);
doIt(1, 0);
}
}
The output of the above program is:
x: 0, y: 0
f2. a: 1, b: 0
f2. a: 0, b: -1
x: 1, y: 0
f1. a: 2, b: 0
f1. a: 1, b: -1
You can combine the function together.
Using a switch.
public static boolean func(int a, int b, int fun)
{
boolean output = false;
switch(fun)
{
case 1:
//do stuff
output = true;
break;
case 2:
//do stuff
output = true;
break;
default:
//unknown function handling
output = false;
}
return output;
}
Integrate it with a for-loop:
public static void main(String[] args)
{
int i;
//Change this to whatever you want or set it to a argument.
int repeat = 2;
for(i = 1; i <= repeat; i++)
{
func(a, b, i);
}
}
I am working on a problem to try to find what is called a Snake Sequence in a typical XY graph (aka grid). A Snake sequence is defined as a sequence of numbers where each new number, which can only be located to the right or down of the current number, is either plus or minus one. For example, if you are in the center of the graph, you can either move right (if that number is + or - 1) or move down (if that number is + or - 1). The goal of the problem is to find the longest path (aka Snake Sequence) through the graph (keeping in mind you can only chart a path to a new cell whose value is +- 1 with the current cell).
So, for the following XY graph, the longest snake sequence is: 9, 8, 7, 6, 5, 6, 7
9, 6, 5, 2
8, 7, 6, 5
7, 3, 1, 6
1, 1, 1, 7
Below is my code, which does not seem to work.
Question: How would you solve this problem above? (I offer my code showing what I have thus far, but it does not work)
import java.util.ArrayList;
public class SnakeSequence {
private final int maxX = 3;
private final int maxY = 3;
private final int[][] board = new int[][]{
{1, 2, 3, 4},
{2, 1, -1, 5},
{3, 0, -1, 6},
{6, 2, 1, 7}
};
private ArrayList<Integer> findSequence(int xPos,
int yPos, ArrayList<Integer> currentPath) {
currentPath.add(board[yPos][xPos]);
ArrayList<Integer> pathRight = new ArrayList<Integer>(currentPath);
ArrayList<Integer> pathDown = new ArrayList<Integer>(currentPath);
if (xPos < maxX || yPos < maxY) {
if (yPos < maxY && (board[yPos + 1][xPos] + 1 == board[yPos][xPos] ||
board[yPos + 1][xPos] - 1 == board[yPos][xPos])) {
pathDown = findSequence(xPos, yPos + 1, currentPath);
}
if (xPos < maxX && (board[yPos][xPos + 1] + 1 == board[yPos][xPos] ||
board[yPos][xPos + 1] - 1 == board[yPos][xPos])) {
pathRight = findSequence(xPos + 1, yPos, currentPath);
}
if (pathDown.size() > pathRight.size()) {
return pathDown;
} else {
return pathRight;
}
}
return currentPath;
}
private void getSequence() {
ArrayList<Integer> currentPath = new ArrayList<Integer>();
ArrayList<Integer> result;
result = findSequence(0, 0, currentPath);
for (int i = 0; i < result.size(); i++) {
System.out.println(result.get(i));
}
}
public static void main(String[] args) {
SnakeSequence sequence = new SnakeSequence();
sequence.getSequence();
}
}
You can imagine your table as an oriented graph, then you problem is just to find the longest path.
Fortunatly for you, only moving down and right is allowed, so your graph is acyclic, so you can use algorithms like critical path method.
This is how your graph would look like:
However, you want to find longest path between any two cells. To do that, I would compute for each cell the longest path starting at that cell. It is simmilar to what you do, but you compute same thing more times. Consider this:
6 -> 5
| |
v v
7 -> 6
At both 5 and 7 you compute how long is the path from 6 at down right, and that is useless repeated computation. In worst case scenario, this could lead to exponential time consumption, while the problem can be resolved in linear time!
Moreover, there is no guarantee that the longest path will start at (0,0).
(one possible) Solution:
Compute longest path from each cell, starting from bottom-right to upper-left. At each cel.. remember how long the longest path from that cell is, and witch way from that cell the path leads. (I will measure path length by number of cells on it). So for example, for the only 8 in your grapth, we would remeber [length=8, direction=right].
Why so complicated? Because it is now extramly easy to compute longest path at a cell, if we know the longest path of the cells to the right and down. Example (I made up):
The correct data for 2 now would be [length=4, direction=down] because can't go from 2 to 4.
You can also keep globally longest path and it's start. After the computation is complete, just walk the longest path from that start through the direction and write the numbers, position or whatever you need.
Apologies for my Java (I am primarily a c# programmer) but here is one solution. I separated out the algorithm that discovers the snakes from the algorithm (implementing the interface ISnakeProcessor) that processes each one. That way you could enhance the code to, e.g., collect the snake with the largest sum of values, or collect all the longest snakes, in case there are more than one, by adding more ISnakeProcessor classes.
import java.util.*;
import java.lang.*;
class Rextester
{
public static void main(String args[])
{
SnakeSequence sequence = new SnakeSequence();
sequence.getSequence();
}
}
interface ISnakeProcessor
{
void process(List<Pair<Integer, Integer>> snake);
}
class SnakeSequence {
private final int[][] board;
public SnakeSequence()
{
this(new int[][]{
{1, 2, 3, 4},
{2, 1, -1, 5},
{3, 0, -1, 6},
{6, 2, 1, 7}
});
}
public SnakeSequence(int[][] board)
{
this.board = board;
}
public boolean isValid(int iRow, int iCol)
{
if (iRow < 0 || iRow >= board.length)
return false;
if (iCol < 0 || iCol >= board[iRow].length)
return false;
return true;
}
private boolean continuesInRow(int iRow, int iCol)
{
if (!isValid(iRow, iCol) || !isValid(iRow+1, iCol))
return false;
int myVal = board[iRow][iCol];
if (board[iRow+1][iCol] == myVal - 1 || board[iRow+1][iCol] == myVal + 1)
return true;
return false;
}
private boolean continuesInCol(int iRow, int iCol)
{
if (!isValid(iRow, iCol) || !isValid(iRow, iCol+1))
return false;
int myVal = board[iRow][iCol];
if (board[iRow][iCol+1] == myVal - 1 || board[iRow][iCol+1] == myVal + 1)
return true;
return false;
}
private boolean isHead(int iRow, int iCol)
{
if (!isValid(iRow, iCol))
return false;
if (isValid(iRow-1, iCol) && continuesInRow(iRow-1, iCol))
return false;
if (isValid(iRow, iCol-1) && continuesInRow(iRow, iCol-1))
return false;
return true;
}
private boolean isTail(int iRow, int iCol)
{
if (!isValid(iRow, iCol))
return false;
if (continuesInRow(iRow, iCol))
return false;
if (continuesInCol(iRow, iCol))
return false;
return true;
}
private void testHead()
{
System.out.println("Dumping list of heads");
for (int iRow = 0; iRow < board.length; iRow++)
{
for (int iCol = 0; iCol < board[iRow].length; iCol++)
{
boolean head = isHead(iRow, iCol);
boolean tail = isTail(iRow, iCol);
if (head && tail)
System.out.print(" B");
else if (head)
System.out.print(" H");
else if (tail)
System.out.print(" T");
else
System.out.print(" -");
}
System.out.println("");
}
}
private void walkSnake(ISnakeProcessor processor, int iRow, int iCol, ArrayList<Pair<Integer, Integer>> snake)
{
snake.add(new Pair<Integer, Integer>(iRow, iCol));
boolean isTail = true;
if (continuesInRow(iRow, iCol))
{
walkSnake(processor, iRow+1, iCol, snake);
isTail = false;
}
if (continuesInCol(iRow, iCol))
{
walkSnake(processor, iRow, iCol+1, snake);
isTail = false;
}
if (isTail)
{
processor.process(snake);
}
snake.remove(snake.size() - 1);
}
private void walkSnakes(ISnakeProcessor processor)
{
ArrayList<Pair<Integer, Integer>> snake = new ArrayList<Pair<Integer, Integer>>();
for (int iRow = 0; iRow < board.length; iRow++)
for (int iCol = 0; iCol < board[iRow].length; iCol++)
if (isHead(iRow, iCol))
walkSnake(processor, iRow, iCol, snake);
}
class LongestSnakeFinder implements ISnakeProcessor
{
private final SnakeSequence parent;
ArrayList<Pair<Integer, Integer>> longest = new ArrayList<Pair<Integer, Integer>>();
public LongestSnakeFinder(SnakeSequence parent)
{
this.parent = parent;
}
public void process(List<Pair<Integer, Integer>> snake)
{
if (snake.size() > longest.size())
{
longest.clear();
longest.addAll(snake);
}
}
public void dumpLongest()
{
System.out.format("The first encountered longest snake has length %d:\n", longest.size());
for (int i = 0; i < longest.size(); i++)
{
int iRow = longest.get(i).getFirst();
int iCol = longest.get(i).getSecond();
System.out.format(" (%d,%d): %d\n", iRow, iCol, parent.getValue(iRow, iCol));
}
}
}
public int getNRows() { return board.length; }
public int getNCols(int iRow) { return board[iRow].length; }
public int getValue(int iRow, int iCol) { return board[iRow][iCol]; }
public void getSequence() {
testHead();
LongestSnakeFinder finder = new LongestSnakeFinder(this);
walkSnakes(finder);
finder.dumpLongest();
}
}
class Pair<F, S> {
private F first; //first member of pair
private S second; //second member of pair
public Pair(F first, S second) {
this.first = first;
this.second = second;
}
public F getFirst() {
return first;
}
public S getSecond() {
return second;
}
}
Example run here: http://rextester.com/AKUFNL43897
Update - cleaned code a little. New sample run here: http://rextester.com/AVOAIY11573
And, the output:
Dumping list of heads
H - - -
- - B -
T - T -
B H T T
The first encountered longest snake has length 7:
(0,0): 1
(0,1): 2
(0,2): 3
(0,3): 4
(1,3): 5
(2,3): 6
(3,3): 7
Is this what you want?
Here is one simple way to correct your solution and avoid copying of path on every step
import java.util.ArrayList;
import java.util.Collections;
public class SnakeSequence {
private final int maxX = 3;
private final int maxY = 3;
private final int[][] board = new int[][]{
{1, 2, 3, 4},
{2, 1, -1, 5},
{3, 0, -1, 6},
{6, 2, 1, 7}
};
private ArrayList<Integer> findSequence(int xPos,
int yPos) {
ArrayList<Integer> pathRight = new ArrayList<Integer>();
ArrayList<Integer> pathDown = new ArrayList<Integer>();
if (yPos < maxY && (board[yPos + 1][xPos] + 1 == board[yPos][xPos] ||
board[yPos + 1][xPos] - 1 == board[yPos][xPos])) {
pathDown = findSequence(xPos, yPos + 1);
}
if (xPos < maxX && (board[yPos][xPos + 1] + 1 == board[yPos][xPos] ||
board[yPos][xPos + 1] - 1 == board[yPos][xPos])) {
pathRight = findSequence(xPos + 1, yPos);
}
ArrayList<Integer> ans;
if (pathDown.size() > pathRight.size()) {
ans = pathDown;
} else {
ans = pathRight;
}
ans.add(board[yPos][xPos]);
return ans;
}
private void getSequence() {
ArrayList<Integer> result;
result = findSequence(0, 0);
Collections.reverse(result);
for (int i = 0; i < result.size(); i++) {
System.out.println(result.get(i));
}
}
public static void main(String[] args) {
SnakeSequence sequence = new SnakeSequence();
sequence.getSequence();
}
}
But this way it can work much faster for big arrays due to no recalculating the longest path every time you visiting the same number during recursion. Actually, in this version each number is visited at most twice. It's achieved through saving best solution for every node. Separate storage of path and it length allows not to copy path when it's not needed.
import java.util.ArrayList;
import java.util.Collections;
public class SnakeSequence {
private final int maxX = 3;
private final int maxY = 3;
private final int[][] board = new int[][]{
{1, 2, 3, 4},
{2, 3, -1, 5},
{3, 2, -1, 6},
{6, 1, 2, 3}
};
int[][] pathLength;
ArrayList<ArrayList<ArrayList<Integer>>> paths;
private ArrayList<Integer> findSequence(int xPos,
int yPos) {
if(pathLength[yPos][xPos] >= 0)
{
ArrayList<Integer> ans = new ArrayList<Integer>();
int length = pathLength[yPos][xPos];
ArrayList<Integer> path = paths.get(yPos).get(xPos);
for(int i = 0; i < length; i++)
ans.add(path.get(i));
return ans;
}
ArrayList<Integer> pathRight = new ArrayList<Integer>();
ArrayList<Integer> pathDown = new ArrayList<Integer>();
if (yPos < maxY && (board[yPos + 1][xPos] + 1 == board[yPos][xPos] ||
board[yPos + 1][xPos] - 1 == board[yPos][xPos])) {
pathDown = findSequence(xPos, yPos + 1);
}
if (xPos < maxX && (board[yPos][xPos + 1] + 1 == board[yPos][xPos] ||
board[yPos][xPos + 1] - 1 == board[yPos][xPos])) {
pathRight = findSequence(xPos + 1, yPos);
}
ArrayList<Integer> ans;
if (pathDown.size() > pathRight.size()) {
ans = pathDown;
} else {
ans = pathRight;
}
ans.add(board[yPos][xPos]);
paths.get(yPos).set(xPos,ans);
pathLength[yPos][xPos] = ans.size();
return ans;
}
private void getSequence() {
ArrayList<Integer> result;
pathLength = new int[maxX + 1][maxY + 1];
paths = new ArrayList<ArrayList<ArrayList<Integer>>>();
for(int y = 0; y <= maxY; y++)
{
ArrayList<ArrayList<Integer>> line = new ArrayList<ArrayList<Integer>>();
for(int x = 0; x <= maxX; x++)
{
line.add(null);
pathLength[y][x] = -1;
}
paths.add(line);
}
result = findSequence(0, 0);
Collections.reverse(result);
for (int i = 0; i < result.size(); i++) {
System.out.println(result.get(i));
}
}
public static void main(String[] args) {
SnakeSequence sequence = new SnakeSequence();
sequence.getSequence();
}
}
Simple Recursive solution :
import java.util.ArrayList;
import java.util.List;
public class MaximumLengthSnakeSequence {
static int max = -1;
static List<Integer> maxListTemp = new ArrayList<>();
public static void main(String args[]) {
int count = 0;
int n = 4;
int m = 4;
int mat[][] = { { 9, 6, 5, 2 }, { 8, 7, 6, 5 }, { 7, 3, 1, 6 }, { 1, 1, 1, 7 }, };
List<Integer> maxList = new ArrayList<>();
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
List<Integer> list = new ArrayList<>();
list.add(mat[i][j]);
List<Integer> testList = recur(i, j, count, mat, n, m, list);
if (maxList.size() < testList.size()) {
maxList = new ArrayList<>(testList);
}
maxListTemp.clear();
}
}
System.out.println("max is " + maxList);
}
static List<Integer> recur(int i, int j, int count, int mat[][], int n, int m, List<Integer> list) {
int curData = mat[i][j];
int rightData = 0;
int downData = 0;
if (j + 1 < n && i < m) {
rightData = mat[i][j + 1];
if (Math.abs(curData - rightData) == 1) {
list.add(rightData);
recur(i, j + 1, count + 1, mat, n, m, list);
list.remove(list.size() - 1);
}
}
if (count > max) {
max = count;
}
if (maxListTemp.size() < list.size()) {
maxListTemp = new ArrayList<>(list);
}
if (i + 1 < m && j < n) {
downData = mat[i + 1][j];
if (Math.abs(curData - downData) == 1) {
list.add(downData);
recur(i + 1, j, count + 1, mat, n, m, list);
list.remove(list.size() - 1);
}
}
return maxListTemp;
}
}
Given an array of integers f, I want to see if f[k]=k for some k in the array. I'm having some trouble because I would like to return on the left and right half of the array, but I am not sure how to go about doing that. This is what I have so far:
public class Find {
int a = 0;
public boolean find(int[] f) {
if(f.length < 1) {
return false;
}
System.out.println(f[0] + " " + a);
if(f.length == 1 && f[0] == a) {
return true;
}
if(f.length == 1 && f[0] != a) {
return false;
}
int[] L = Arrays.copyOfRange(f, 0, f.length / 2);
int[] R = Arrays.copyOfRange(f, f.length / 2, f.length);
find(L);
a++;
//find(R);
return find(R); //only finds in the right half...
}
public static void main(String[] args) {
Find F = new Find();
int[] test = {0, 13, 2, 3, 4};
System.out.println(F.find(test));
}
}
You could do the following, you currently search the left side but do not return the result:
return find(R) || find(L);