recursive search in java - java

I have the following problem:
I have a hashset of Pairs. Pair is a pair of ints. the pair represents "likes".
let's say my set is :<1,2>,<2,1>,<3,1>,<6,7>,<5,7>,<2,6>
this means 1 likes 2 and 2 likes 1 and 3 likes 1 and so on...
What I'm requested to do is to look at those relations as a graph and given two numbers let's say 2 and 6 I have to find whether there is a route in a graph from 2 to 6 with at most 5 edges connecting between them...
how to write a short recursive method that calculates if the route exists?
I wrote the following code:
private boolean findPath(int from, int to, int count){
System.out.println(from+" "+to+" "+count);
if(from==to && count<=5)
return true;
if(count>5)
return false;
Iterator<CookingParty.Pair> iter=likesSet.iterator();
while(iter.hasNext()){
Pair curr=iter.next();
if(curr.likes==from && curr.liked==to){
return true;
}
if(curr.likes==from)
return findPath(curr.liked, to, count+1);
}
return false;
}
the problem is that it won't continue going over the rest of the possibilities once one was found to be wrong.
how can I change it to work?
this is the update:
private boolean findPath(int from, int to, int count){
System.out.println(from+" "+to+" "+count);
if(from==to && count<=5)
return true;
if(count>5)
return false;
Iterator<CookingParty.Pair> iter=likesSet.iterator();
boolean found=false;
while(iter.hasNext() && !found){
Pair curr=iter.next();
if(curr.likes==from && curr.liked==to){
found=true;
return found;
}
if(curr.likes==from)
return findPath(curr.liked, to, count+1);
}
return found;
}

Currently you return as soon as you find a pair where curr.likes == from. To explore also other paths, you mustn't immediately return in the while loop, but while you haven't yet found a path, check for further possibilities.
boolean found = false;
while(iter.hasNext() && !found){
// check a path
}
return found;
Re update: You are still returning in the loop. That's okay in the case where you found a path, but you absolutely must not return in the general case. If curr.likes == from and curr.liked != to, check that path and update the boolean, do not return. Return after the loop has finished.

To search for a path in a graph you can use Depth-First or Breadth-First search. Depth-first is traditionally recursive because it uses a stack. Have a look at the pseudocode here:
http://en.wikipedia.org/wiki/Depth-first_search#Pseudocode

Related

How do you check if a number is in a list with Java (no given parameters)

public int FirstNineIndexFromStart() {
if (first != null) {
if(this.first.item == 9.0)
return 0;
int index = 0;
for (Node i = this.first; i != null; i = i.next) {
if (i.item == 9.0)
return index;
index+=1;
}
return index;
}
return -1;
}
The goal of the project is to check the first index that the number 9 is at in a list from the start.
The two conditionals that must be met are that, if a list begins with the number 9, return the position number 0. If the list does not contain a 9 at all, return a -1.
Everything runs fine - EXCEPT if a 9 is not in the list. My test code gives me the wrong answer. It is not spitting out a -1 to be accounted for. Can someone please tell me how to make sure that, if a 9 is not present, it returns a -1?
I cannot use functions for this either. So, I cannot use contains().
If the loop completes, the number was not found. Change the second return index; to return -1;.
Note that there's no need for a special case for the first item. The loop should do the job just fine.

Can anyone spot the error that i am making?

All test case is running successfully except one which is in1To10(9, true) → false.
Question:
Given a number n, return true if n is in the range 1..10,
inclusive. Unless outsideMode is true, in which case return true if
the number is less or equal to 1, or greater or equal to 10.
in1To10(5, false) → true
in1To10(11, false) → false
in1To10(11, true) → true
My Solution:-
public boolean in1To10(int n, boolean outsideMode) {
if(n>=1&&n<=10){
return true;
}
else if(outsideMode==true&&(n<=1||n>=10)){
return true;
}else
return false;
}
As you have mentioned in problem the return boolean value is based on boolean value of outsideMode and the range (1-10) value
But in your program the first return statement value is decided by only the range criteria you did't test the boolean value of outsideMode.
1. Solution :
Either swap the second if(condition) with first if(condition)
public boolean in1To10(int n, boolean outsideMode) {
if((outsideMode==false)&&(n>=1&&n<=10)){
return true;
}
else if(outsideMode==true&&(n<=1||n>=10)){
return true;
}else
return false;
}
2.Solution:
include the outsideMode with first if(condition) same like second if(condition)
public boolean in1To10(int n, boolean outsideMode) {
if(outsideMode==true&&(n<=1||n>=10)){
return true;
}
else if(n>=1&&n<=10){
return true;
}else
return false;
}
When you say "all test cases are running successfully", that is rather misleading since you have too few test cases.
For each interesting integer comparison you need 2 test cases: one in which the comparison succeeds and one in which it fails. As test data you should pick the two integers that make the difference. For example, if the condition is n > 10, you should use 10 and 11 as test data.
In your scenario you have a boolean, and in each case of that boolean you have two integer conditions. Altogether, that makes 2 * 2 * 2 = 8 test cases. That is much more than the 3 test cases that you currently have, but it's necessary.
By testing your code systematically you will produce more reliable code than without these tests, even if it takes some time. But in return you get more confidence in the code, and that is worth it.
Further reading: test coverage, condition coverage.
First of all outsideMode is a boolean so just writte outisdeMode&&(n<=1||n>=10)
Your error is that
if(n>=1&&n<=10){
return true;
}
Will be executed befor
else if(outsideMode==true&&(n<=1||n>=10))
Because 9 >= 1 && 9 <= 10 which means that it will return true
Swap them and you will be fine
public boolean in1To10(int n, boolean outsideMode) {
if(outsideMode&&(n<=1||n>=10)){
return true;
}
else if(!outsideMode&&n>=1&&n<=10){
return true;
}else
return false;
}

Wrap Around Grid - errors on east/west only

I have four methods that check whether or not a given grid location is next to an occupied location (value of 1). The grid is assumed to wrap around, ie, if in a 50x50 grid[0][1] is the given location and grid[49][1] is occupied, the method should return true/ My checkNorth and checkEast method are working fine, but I get an ArrayIndexOutofBoundsException: -1 error for either the south or west methods every time I run the program. I checked my math and I think it should work - am I using the modulo incorrectly, or am I missing something else?
EDIT: Clarified the wrapping criterion, word use correction.
boolean checkWest(int indexA, int indexB)
{
if (indexA-1 > 0)
{
if (grid[indexA-1][indexB] == 1)
{
return true;
}
}
if (indexA-1 < 0)
{
if (grid[(indexA-1)%width][indexB] == 1)
{return true;}
else return false;
}
return false;
}
I see a couple problems. First, Java arrays are zero-indexed, which means that the first element is at index 0. So it's okay to check grid[indexA-1][indexB] when indexA-1 is equal to 0. Second, you're not properly handling when indexA equals 0. Here is my implementation. I also simplified the logic a bit.
boolean checkWest(int indexA, int indexB)
{
if (indexA > 0)
return grid[indexA - 1][indexB] == 1;
else
return grid[width + indexA - 2][indexB] == 1;
}
EDIT: I'm pretty sure I butchered the math with the second return statement. It should be right now...

Binary Search using Recursion in java

I am writing a program for a recursive binary search. I have an input file with a series of sorted numbers, which I added to an ArrayList. The program searches to see if a key given by user input is in the ArrayList.
public static int binarySearch(int key, int median){
if(key == (int)array.get(median)){
return key;
}else if(key < (int)array.get(median)){
binarySearch(key,median-1);
}else if(key > (int)array.get(median)){
binarySearch(key,median+1);
}
return -1;
}
For example, let's say the key is 90. I debugged and placed watches at key and array.get(median). After stepping through the program, I discovered that even when key and array.get(median) are equal to 90, the program continues through the loop without ever returning the key. I know that recursion isn't ideal for this, but it's what I need to use.
This does not look like a correct binary search, as a binary search uses a divide and conquer approach. You only divide your list initially once and then check every element from there on. It would be better to then just divide your list again and so on, see https://en.wikipedia.org/wiki/Binary_search_algorithm
Anyway, to get your code running, why you do not get an result is most likely because you do not return the result of the recursion, but instead -1.
Remove the return -1 and set a return before your recursive binarySearch calls. And you are missing a exit condition when you do not find the element.
Example (still not a correct binary search):
public static int binarySearch(int key, int median){
if (median < 0 || median > array.size() - 1) { // element not found
return -1;
}
if (key == (int)array.get(median)){
return key;
} else if(key < (int)array.get(median)){
return binarySearch(key,median-1);
} else{
return binarySearch(key,median+1);
}
}
If all you care about is whether it is in the data structure...
public static boolean binarySearch(int key, int median){
if(key == (int)array.get(median)){
return true;
}else if(key < (int)array.get(median)){
return binarySearch(key,median-1);
}else if(key > (int)array.get(median)){
return binarySearch(key,median+1);
}
}
your code could be better written, but copied to to get across the important part of it
You should change your code like this:
public static int binarySearch(int key, int median){
if(key == (int)array.get(median)){
return key;
}else if(key < (int)array.get(median)){
return binarySearch(key,median-1);
}else if(key > (int)array.get(median)){
return binarySearch(key,median+1);
}
return -1;
}
If you do this your recursion would end but I will leave it to you to test out your binary search code. There are some things like the start index and the end index that you are ignoring in this method The return statements should be added because if you don't the control moves to the next statement in the method which is undesirable. Hope that helps!
The code posted is not a Binary Search and is, in fact, a Linear Search using recursion. A Binary Search divides the search space in half each step, binary meaning "two halves" in context. The result is that this Linear Search runs in O(n) and not the expected O(lg n) bounds of a Binary Search
Problems/issues (other than it not being a Binary Search):
The values from the recursive cases are lost as they are not themselves returned. The result of a recursive case must be used in some way (or why call the function at all?). In this case the value should be returned directly, eg. return binarySearch(..). This causes "continues through the loop without ever returning the key" - it actually does find the key, but discards the recursive result.
The code does not correctly detect the out-of-bounds terminal condition. This may result in an IndexOutOfBoundsException when the key is not found.
The step-left/right approach might never terminate correctly without further logic. For example, when the list is {1,3,5,7} and the value being sought is 4 the original code will ping-pong between indices 1 (value 3) and 2 (value 4). This will result in a StackOverflowError being thrown.
The key is returned. This makes little sense as the key is already known and it also prevents -1 from being detectable. Return the index found instead, or a boolean if only an existence test is required.
Take some time to understand and fix these issues .. and then read on for a spoiler if needed.
Consider this rewrite fixing the issues outlined above. Note that it is overly complex1 while still employing an inferior algorithm and O(n) performance. In any case;
// By taking in the List we make this function universal and not
// dependent upon a static field. It should probably take in a List<Integer>
// but I don't know what the actual type of "array" is. A more advanced
// implementation would take in List<Comparable> and then be modified to work
// with any objects that correctly implement said interface.
public static int linearSearch(int key, List list, int index, int step) {
if (index < 0 || index >= list.size()) {
// Base case: not found, out of bounds
return -1;
}
int x = (int)list.get(index);
if (key < x && step <= 0) { // need to look left, NOT looking right
// Recursive case: look left, returning result
return linearSearch(key, list, index - 1, -1);
} else if (key > x && step >= 0){ // need to look right, NOT looking left
// Recursive case: look right, returning result
return linearSearch(key, list, index + 1, +1);
} else if (key == x) {
// Base case: found key, return index found
return index;
} else {
// Base case: key not equal, refusing to ping-pong
return -1;
}
}
And then consider the use of this helper/wrapper function;
// Returns the index in "array" where key was found, or -1 if it was not found
public static int linearSearch(int key) {
// Have to start somewhere, might as well be the middle..
// ..but it does NOT make the time complexity any better
// ..and it is still NOT a Binary Search.
return linearSearch(key, array, array.size() / 2, 0);
}
1 Alternatively, since it is a Linear Search it could be rewritten without the extra left/right movement and have the same complexity bounds. (It is also trivial to modify this simpler code to a recursive Binary Search.)
public static int linearSearch(int key, List list, int index) {
if (index >= list.size() {
// Base case: end of list
return -1;
}
int x = (int)list.get(index);
if (key < x) {
// Recursive case: not there yet, keep looking
return linearSearch(key, list, index + 1);
} else if (key == x) {
// Base case: found key, return index
return index;
} else { // -> key > x
// Base case: read past where the key would be found
return -1;
}
}
Here's binary search for ArrayList<Integer> :)
public int binarySearch(List<Integer> list, int find) {
int mid = list.size() / 2;
int val = list.get(mid);
if (val == find) {
return val;
} else if (list.size() == 1) {
return -1;
}
return val > find ?
binarySearch(list.subList(0, mid), find) :
binarySearch(list.subList(mid, list.size()), find);
}

Solving sudoku by recursion

I tried writing recursion to solve sudoku, and I'm having a problem with the recursion.
If it's unsolvable its ok, but if it is solvable it is getting to infinite loop.
public static boolean recursion (int sodukuMatrix[][],int posRow, int posCol ,int i){
if (posRow==0 && posCol==0 && i==10)
return false;
if(there is existing number){
if (posCol==8 && posRow==8)
return true;
call recursion with next square
}
else {
i=sodukuMatrix[posRow][posCol]+1;
while (i<10){
if (function: if I put i at the current location it is ok){
sodukuMatrix[posRow][posCol]=i;
if (posCol==8 && posRow==8)
return true;
call recursion with next square
}
else
i++;
}
sodukuMatrix[posRow][posCol]=0;
return false;
}
return false;
}
}
To go a little down the rabbit hole. Solving Sudoko seems like an application of Constraint-Satisfaction in a context similar to the N-Queens Problem A MIN-CONFLICTS algorithm can be used in combination with Simulated Annealing to find the optimal solution.
Consider this pseudocode from Peter Norvig's Artificial Intelligence a Modern Approach
function MIN-CONFLICTS(csp, max_steps) returns a solution or failure
inputs: csp, a constraint satisfaction problem
max_steps, the number of steps allowed before giving up
current <- an initial complete assignment for csp
for I = 1 to max_steps do
if current is a solution for csp then return current
var <- a randomly chosen conflicted variable from csp.VARIABLES
value <- the value v for var that minimizes CONFLICTS(var, v, current, csp)
set var = value in current
return failure
The CONFLICTS function counts the number of constraints violated by a particular value, given the rest of the current assignment.

Categories