So as the title suggests, I am writing some code to perform a version of a binary search in Java. However, my return statements are ignored and the function instead returns the last "catch all" return statement as shown below:
public int binarySearch(int min, int max) {
int mid = ((min+max)/2);
double[][] m1 = createFilledSquareMatrix(mid);
double[][] m2 = createFilledSquareMatrix(mid);
double[][] m3 = new double[mid][mid];
long time = analyzeMultiply(m1, m2, m3);
if(time == 1000) {
return mid;
}
if (time > 1000) {
m1 = createFilledSquareMatrix(mid-1);
m2 = createFilledSquareMatrix(mid-1);
m3 = new double[mid-1][mid-1];
time = analyzeMultiply(m1, m2, m3);
if(time <= 1000) {
return mid; //I am reached but ignored
}
else {
binarySearch(min, mid-1);
}
}
else {
System.out.println("here");
m1 = createFilledSquareMatrix(mid+1);
m2 = createFilledSquareMatrix(mid+1);
m3 = new double[mid+1][mid+1];
time = analyzeMultiply(m1, m2, m3);
if(time >= 1000) {
return mid+1; //I am reached but ignored
}
else {
binarySearch(mid+1, max);
}
}
return -2;
}
So I have commented the return statements that are ignored. I go through with the debugger and it executes the return but then just goes to the outter return -2 statement and then executes that. I've never had this type of issue before so I feel like I am missing something simple. Any help would be appreciated.
Your method is recursive. This means that every time you recurse, you need to do something with the returned value from the recursive call. What you are seeing is that the recursive calls reach a termination point, return a value, and then bubble back out. However since the instance that made the recursive call doesn't do anything with the returned value, it continues executing as if nothing happened, causing it to drop back to it's "catch all" return instead, and so on.
For example,
else {
binarySearch(min, mid-1);
}
should be
else {
return binarySearch(min, mid-1);
}
Related
The below code works fine for attached input.
public class Solution {
public boolean wordBreak(String s, List<String> wordDict) {
return wordBreakMemo(s, new HashSet<>(wordDict), 0, new Boolean[s.length()]);
}
private boolean wordBreakMemo(String s, Set<String> wordDict, int start, Boolean[] memo) {
if (start == s.length()) {
return true;
}
if (memo[start] != null) {
return memo[start];
}
for (int end = start + 1; end <= s.length(); end++) {
if (wordDict.contains(s.substring(start, end)) && wordBreakMemo(s, wordDict, end, memo)) {
return memo[start] = true;
}
}
return memo[start] = false;
}
}
But when I change the local variables to global as below, my code take longer to execute, resulting in 'Time Limit Exceeded' on LeetCode.
class Solution {
HashSet<String> set;
String s;
Boolean dp[];
public boolean wordBreak(String s, List<String> wordDict) {
set=new HashSet();
set.addAll(wordDict);
this.s=s;
dp=new Boolean[s.length()];
return wordMemo(0);
}
public boolean wordMemo(int start)
{
if(start==s.length())
return true;
if(dp[start]!=null)
return dp[start];
for(int i=start+1; i<=s.length(); i++)
{
if(set.contains(s.substring(start, i)) && wordMemo(i))
{
dp[start]=true;
return true;
}
}
return false;
}
}
Input:
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab"
["a","aa","aaa","aaaa","aaaaa","aaaaaa","aaaaaaa","aaaaaaaa","aaaaaaaaa","aaaaaaaaaa"]
Can someone please explain what is happening around here?
Global variables don't have slower fetch times, no.
Whenever you get Time Limit Exceeded in a coding challenge you should assume you have a a flawed or buggy algorithm or data structure. It's never micro factors like fetch times or access modifiers or the language you've chosen. Even if you could speed up your program 10% with better memory access patterns or 100% by switching from Python to C, you're probably off by 10,000% or 10,000,000%, not 100%. That's how bad it can be when your program is accidentally O(n2) or O(2n) when the challenge designers expect O(n).
Here, the first program has:
return memo[start] = false;
While the second one has just:
return false;
It never memoizes false results. There are a lot more repeated computations, enough to kill the algorithm's Big-O time complexity.
I have found that my method called checkForErrors takes around 80x longer to run on the first execution only, and I can't seem to figure out why.
D/guess: adhl
D/checkerror: checking for errors took 4760743ns // first run
D/validity: checking guess validity took 7141114ns
D/guess: agkl
D/checkerror: checking for errors took 61035ns // every other run takes around this long
D/validity: checking guess validity took 732422ns
I have looked through the code and I don't see anything that would take longer on the first run only so I'm stumped.
Button on click listener:
submitBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String Guess = guess_txt.getText().toString();
Log.d("guess", Guess);
if(checkGuessValidity(Guess)){ // <--
submitValidGuess(Guess);
int bulls = game.getBullsAndHits()[0];
int hits = game.getBullsAndHits()[1];
if(!game.gameWon) //if game is not won, submit the guess with bulls and hits
guessSubmittedListener.guessSubmitted(Guess, bulls, hits);
else //if game is won, call gameWon() method
gameEnd();
}
if((game.getCurrentTry() > game.getMaxTries()) && (!Guess.equals(game.getHiddenWord()))) gameEnd(); //if user is out of tries, call gameLost method
triesLeft.setText("Tries Left: " + (game.getMaxTries() - game.getCurrentTry() + 1)); //update tries left on main fragment
guess_txt.setText("");
}
});
checkGuessValidity:
public boolean checkGuessValidity(String Guess){
long start = System.nanoTime();
long start2 = System.nanoTime();
ErrorList Status = checkForErrors(Guess); // <--
long end2 = System.nanoTime();
Log.d("checkerror", "checking for errors took " + (end2 - start2) + "ns");
. . . more code . . .
checkForErrors:
public ErrorList checkForErrors(String Guess){
if(Guess.length() != game.getHiddenWordLength()) return ErrorList.Wrong_Length;
else if(!isValidInput(Guess)) return ErrorList.Invalid_Characters;
else if(!isIsogram(Guess)) return ErrorList.Not_Isogram;
else if(!isLowercase(Guess)) return ErrorList.Not_Lowercase;
else return ErrorList.OK;
}
isValidInput, isIsogram and isLowercase:
public boolean isIsogram(String Guess){
Map<Character, Boolean> map = new HashMap();
for(int i = 0; i < Guess.length(); i++){
if(map.get(Guess.charAt(i)) == null) //if the value for the key (character) is null (has not been changed since map initialization)
map.put(Guess.charAt(i), true); //then set it to true (indicating that it has been seen)
else { //else (if the value at the character HAS been changed since initialization, ie. it has been seen)
Log.d("Character repeated", "" + Guess.charAt(i));
return false; //return false
}
}
return true; //if loop completes no duplicates were found and guess is an isogram
}
public boolean isLowercase(String Guess){
if(Guess.equals(Guess.toLowerCase())) return true;
else return false;
}
public boolean isValidInput(String Guess){
char[] chars = Guess.toCharArray();
for(int i = 0; i < chars.length; i++){
if(!isLatinLetter(chars[i])) return false;
}
return true;
}
public static boolean isLatinLetter(char c) {
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
}
It doesn't seem like any of the methods should be impacted by when they are run, so I don't know why it takes extra long on the first execution. I'm still a beginner to programming so please excuse any poor formatting or horribly optimized code :p .
edit: CPU usage graph: https://prnt.sc/ftjokq
I just discovered the project euler website, I have done challenges 1 and 2 and have just started number 3 in java... here is my code so far:
import java.util.ArrayList;
public class IntegerFactorise {
private static int value = 13195;
private static ArrayList<Integer> primeFactors = new ArrayList<Integer>();
private static int maxPrime = 0;
/**
* Check whether a give number is prime or not
* return boolean
*/
public static boolean isPrimeNumber(double num) {
for(int i = 2; i < num; i++) {
if(num % i == 0) {
return false;
}
}
return true;
}
/*Multiply all of the prime factors in the list of prime factors*/
public static int multiplyPrimeFactors() {
int ans = 1;
for(Integer i : primeFactors) {
ans *= i;
}
return ans;
}
/*Find the maximum prime number in the list of prime numbers*/
public static void findMaxPrime() {
int max = 0;
for(Integer i : primeFactors) {
if(i > max) {
max = i;
}
}
maxPrime = max;;
}
/**
* Find all of the prime factors for a number given the first
* prime factor
*/
public static boolean findPrimeFactors(int num) {
for(int i = 2; i <= num; i++) {
if(isPrimeNumber(i) && num % i == 0 && i == num) {
//could not possibly go further
primeFactors.add(num);
break;
}
else if(isPrimeNumber(i) && num % i == 0) {
primeFactors.add(i);
findPrimeFactors(num / i);
}
}
int sumOfPrimes = multiplyPrimeFactors();
if(sumOfPrimes == value) {
return true;
}
else {
return false;
}
}
/*start here*/
public static void main(String[] args) {
boolean found = false;
for(int i = 2; i < value; i++) {
if(isPrimeNumber(i) && value % i == 0) {
primeFactors.add(i);
found = findPrimeFactors(value / i);
if(found == true) {
findMaxPrime();
System.out.println(maxPrime);
break;
}
}
}
}
}
I am not using the large number they ask me to use yet, I am testing my code with some smaller numbers, with 13195 (their example) i get down to 29 in this bit of my code:
else if(isPrimeNumber(i) && num % i == 0) {
primeFactors.add(i);
findPrimeFactors(num / i);
}
}
int sumOfPrimes = multiplyPrimeFactors();
if(sumOfPrimes == value) {
return true;
}
It gets to the break statement then finally the check and then the return statement.
I am expecting the program to go back to the main method after my return statement, but it jumps up to:
findPrimeFactors(num / i);
and tries to finish the iteration...I guess my understanding is a flawed here, could someone explain to me why it is behaving like this? I can't wait to finish it of :) I'll find a more efficient way of doing it after I know I can get this inefficient one working.
You are using recursion, which means that a function will call itself.
So, if we trace what your function calls are when you call return, we will have something like that:
IntegerFactorise.main()
|-> IntegerFactorise.findPrimeFactors(2639)
|-> IntegerFactorise.findPrimeFactors(377)
|-> IntegerFactorise.findPrimeFactors(29) -> return true;
So, when you return in the last findPrimeFactors(), you will only return from this call, not from all the stack of calls, and the execution of the previous findPrimeFactors() will continue just after the point where you called findPrimeFactors().
If you want to return from all the stack of calls, you have to modify your code to do something like that:
else if(isPrimeNumber(i) && num % i == 0) {
primeFactors.add(i);
return findPrimeFactors(num / i);
}
So that when the last findPrimeFactors() returns, all the previous findPrimeFactors() which called it will return too.
I think the problem is that you are ignoring the return value from your recursive call to findPrimeFactors().
Let's walk through this. We start with the initial call to findPrimeFactors that happens in main. We then enter the for loop as it's the first thing in that method. Now let's say at some point we get into the else statement and thus recursively call frindPrimeFactors(num / i). This will suspend the looping, but as this recursive call starts to run you enter the for loop again (remember, the previous loop is merely paused and not finished looping yet). This time around you encounter the break, which allows this recursive call to finish out, returning true of false. When that happens you are now back to the original loop. At this point the original loop continues even if the recursive call returned true. So, you might try something like this:
if (findPrimeFactors(num / i))
return true;
I'm assuming that you need to continue looping if the recursive call returned false. If you should always finish looping upon return (whether true or false) then try this:
return findPrimeFactors(num / i);
Is it possible to convert the function go into the non-recursive function? Some hints or a start-up sketch would be very helpful
public static TSPSolution solve(CostMatrix _cm, TSPPoint start, TSPPoint[] points, long seed) {
TSPSolution sol = TSPSolution.randomSolution(start, points, seed, _cm);
double t = initialTemperature(sol, 1000);
int frozen = 0;
System.out.println("-- Simulated annealing started with initial temperature " + t + " --");
return go(_cm, sol, t, frozen);
}
private static TSPSolution go(CostMatrix _cm, TSPSolution solution, double t, int frozen) {
if (frozen >= 3) {
return solution;
}
i++;
TSPSolution bestSol = solution;
System.out.println(i + ": " + solution.fitness() + " " + solution.time() + " "
+ solution.penalty() + " " + t);
ArrayList<TSPSolution> nHood = solution.nHood();
int attempts = 0;
int accepted = 0;
while (!(attempts == 2 * nHood.size() || accepted == nHood.size()) && attempts < 500) {
TSPSolution sol = nHood.get(rand.nextInt(nHood.size()));
attempts++;
double deltaF = sol.fitness() - bestSol.fitness();
if (deltaF < 0 || Math.exp(-deltaF / t) > Math.random()) {
accepted++;
bestSol = sol;
nHood = sol.nHood();
}
}
frozen = accepted == 0 ? frozen + 1 : 0;
double newT = coolingSchedule(t);
return go(_cm, bestSol, newT, frozen);
}
This is an easy one, because it is tail-recursive: there is no code between the recursive call & what the function returns. Thus, you can wrap the body of go in a loop while (frozen<3), and return solution once the loop ends. And replace the recursive call with assignments to the parameters: solution=bestSol; t=newT;.
You need to thinkg about two things:
What changes on each step?
When does the algorithm end?
Ans the answer should be
bestSol (solution), newT (t), frozen (frozen)
When frozen >= 3 is true
So, the easiest way is just to enclose the whole function in something like
while (frozen < 3) {
...
...
...
frozen = accepted == 0 ? frozen + 1 : 0;
//double newT = coolingSchedule(t);
t = coolingSchedule(t);
solution = bestSol;
}
As a rule of thumb, the simplest way to make a recursive function iterative is to load the first element onto a Stack, and instead of calling the recursion, add the result to the Stack.
For instance:
public Item recursive(Item myItem)
{
if(myItem.GetExitCondition().IsMet()
{
return myItem;
}
... do stuff ...
return recursive(myItem);
}
Would become:
public Item iterative(Item myItem)
{
Stack<Item> workStack = new Stack<>();
while (!workStack.isEmpty())
{
Item workItem = workStack.pop()
if(myItem.GetExitCondition().IsMet()
{
return workItem;
}
... do stuff ...
workStack.put(workItem)
}
// No solution was found (!).
return myItem;
}
This code is untested and may (read: does) contain errors. It may not even compile, but should give you a general idea.
I have the following piece of code in Java implementing dynamic programming recursiverelatio:
public double routeCost() throws Exception {
double cost = Double.MAX_VALUE;
for (int l=i; l<=j; l++) {
if (! (customers.get(l) instanceof VehicleCustomer) )
continue;
double value = F(l,j) + (customers.get(l).distanceFrom(depot));
if (value < cost)
cost = value;
}
return cost;
}
private double F(int l, int m) {
//=========================== FIRST CASE ===========================
if (l==i && m==i) {
//System.out.println(i+","+j+","+l+","+m);
return firstCase();
}
//=========================== SECOND CASE ===========================
if (l==i && (i<m && m<=j) ) {
//System.out.println(i+","+j+","+l+","+m);
//analyses the possibility of performing all the soubtours based at heicle customert_i
return secondCase(i,m);
}
//=========================== GENERAL CASE ===========================
else {
System.out.println(i+","+j+","+l+","+m);
assert (customers.get(l) instanceof VehicleCustomer);
assert ( (i<l && l<=j) && (l<=m && m<=j) );
return Math.min(thirdCaseFirstTerm(l,m), thirdCaseSecondTerm(l,m));
}
}
private double firstCase() {
mainRoute.add(depot);
mainRoute.add(customers.get(i));
return depot.distanceFrom(customers.get(i));
}
private double secondCase(int i,int m) {
double caseValue = Double.MAX_VALUE;
int k = i;
while (k<m) {
double totalDemand=0;
for (int u=k+1; ( (u<=m) && (totalDemand<=truckCapacity) ); u++)
totalDemand += customers.get(u).getDemand();
double cost = F(i,k) + thita(i,k+1,m);
if (cost <= caseValue)
caseValue = cost;
k++;
}
return caseValue;
}
private double thirdCaseFirstTerm(int l, int m) {
double caseValue = Double.MAX_VALUE;
int k = i;
while (k<m) {
double totalDemand=0;
for (int u=k+1; ( (u<=m) && (totalDemand<=truckCapacity) ); u++)
totalDemand += customers.get(u).getDemand();
double cost = F(l,k) + thita(l,k+1,m);
if (cost <= caseValue)
caseValue = cost;
k++;
}
return caseValue;
}
private double thirdCaseSecondTerm(int l,int m) {
double caseValue = Double.MAX_VALUE;
int k = i;
for (Customer cust : customers) {
int h = customers.indexOf(cust);
if ( (!(cust instanceof VehicleCustomer)) || (h >=l)) {
continue;
}
double totalDemand=0;
for (int u=k+2; ( (u<=m) && (totalDemand<=truckCapacity) ); u++)
totalDemand += customers.get(u).getDemand();
double cost = F(h,k) + customers.get(h).distanceFrom(customers.get(l)) + thita(l,k+2,m);
if (cost < caseValue)
caseValue = cost;
}
return caseValue;
}
Method F(int,int) is invoked from the for loop in method routeCost().
I want to find a way to enforce that whenever the assertion assert (customers.get(l) instanceof VehicleCustomer);
` is not true, instead of going down to the return statement, I want to infrom the for loop from the routeCost() to continue to the next iteration. But F() has to return a value!
I know that what I'm trying to do violates almost every rule of object orientation, but I really need that.
You could throw an Exception in F() and catch it in routeCost().
This approach is much better than using assertions. They are rarely used in practice, and there's a good reason for this: exceptions are much more flexible and better suited for detecting errors, invalid input etc.
PS: When I say "rarely used", I base this statement on the fact that I saw hundreds of thousands of lines of Java code in the past years and I rarely came accross code that uses assertions.
You can return a special value like Double.NaN which you can check for with Double.isNaN(d)
You could make F() return a Double (instead of double) and return null in the case where your assert fails. Then have your outer for loop do a null check on the returned value before adding it, etc.
Why not replace the asserts with if statements? When the if-statements are true then calculate the value, otherwise return the MAX_VALUE of double. When F returns MAX_VALUE the cost will not be updated.
if (customers.get(l) instanceof VehicleCustomer) {
if ( (i<l && l<=j) && (l<=m && m<=j) ) {
return Math.min(thirdCaseFirstTerm(l,m), thirdCaseSecondTerm(l,m));
}
}
return Double.MAX_VALUE;
Use asserts during development to weed out things that should never happen in private methods. (Asserts can be switched off in production)
Throw an exception when something unexpected happens (e.g. a client of your class passes in invalid data).
However, from your question it seems you expect to get instances that are not VehicleCustomer, so asserts and exceptions are not the right approach here.
Peter Lawrey's and Jeff's answers will also work.