Sudoku Solver by Backtracking not working - algorithm

Assuming a two dimensional array holding a 9x9 sudoku grid, where is my solve function breaking down? I'm trying to solve this using a simple backtracking approach. Thanks!
bool solve(int grid[9][9])
{
int i,j,k;
bool isSolved = false;
if(!isSolved(grid))
isSolved = false;
if(isSolved)
return isSolved;
for(i=0; i<9; i++)
{
for(j=0; j<9; j++)
{
if(grid[i][j] == 0)
{
for(k=1; k<=9; k++)
{
if(legalMove(grid,i,j,k))
{
grid[i][j] = k;
isSolved = solve(grid);
if (isSolved)
return true;
}
grid[i][j] = 0;
}
isSolved = false;
}
}
}
return isSolved;
}
Even after changing the isSolved issues, my solution seems to breakdown into an infinite loop. It appears like I am missing some base-case step, but I'm not sure where or why. I have looked at similar solutions and still can't identify the issue. I'm just trying to create basic solver, no need to go for efficiency. Thanks for the help!

Yea your base case is messed up. In recursive functions base cases should be handled at the start. You got
bool isSolved = false;
if(!isSolved(grid))
isSolved = false;
if(isSolved)
return isSolved;
notice your isSolved variable can never be set to true, hence your code
if(isSolved)
return isSolved;
is irrelevant.
Even if you fix this, its going to feel like an infinite loop even though it is finite. This is because your algorithm has a possible total of 9*9*9 = 729 cases to check every time it calls solve. Entering this function n times may require up to 729^n cases to be checked. It won't be checking that many cases obviously because it will find dead ends when placement is illegal, but whose to say that 90% of the arragements of the possible numbers result in cases where all but one number fit legally? Moreover, even if you were to check k cases on average where k is a small number (k<=10) this would still blow up (run time of k^n.)
The trick is to "try" placing numbers where they will likely result in a high probability of being the actual good placement. Probably the simplest way I can think of doing this is a constraint satisfaction solver, or a search algorithm with a heuristic (like A*.)
I actually wrote a sudoku solver based on a constraint satisfaction solver and it would solve 100x100 sudokus in less than a second.
If by some miracle the "brute force" backtracking algorithm works well for you in the 9x9 case try higher values, you will quickly see a deterioation in run time.
I'm not bashing the backtracking algorithm, in fact I love it, its been shown time and time again that backtracking if implemented correctly can be just as efficient as dynamic programming, however, in your case you aren't implementing it correctly. You are bruteforcing it, you might as well just make your code non-recursive, it will accomplish the same thing.

You refer to isSolved as both a function and a boolean variable.
I don't think this is legal, and its definitely not smart.
Your functions should have distinct names from your variables.

It seems that regardless of whether or not it is a legal move, you are assigning "0" to the square, with that "grid[i][j] = 0;" line. Maybe you meant to put "else" and THEN "grid[i][j] = 0;" ?

Related

Classical bottom-up iterative approach for 0-1 Knapsack variation

I am not good at DP and trying to improve with practice over time. I was trying to solve this problem.
Given prices and favor-value of n items, determine the max value that
you can buy for a pocket money of m. The twist here is that once you
spend above $2000, you can get refund of $200, so effectively your
purchasing power becomes m+200.
I could solve this using recursive approach, but I am more curious to solve it with classical iterative 0-1 Knapsack bottom-up approach as given below, by some modification :
int Knapsack(vector<int> wt, vector<int> val, int cap)
{
int i,j;
int n = wt.size();
for(i=0;i<=n;i++)
t[i][0] = 0;
for(j=0;j<=cap;j++) //cap is the max allowed weight of knapsack
t[0][j] = 0;
for(i=1;i<=n;i++)
{
for(j=1;j<=cap;j++)
{
if(wt[i-1]<=j)
t[i][j] = max(val[i-1]+t[i-1][j-wt[]i-1], t[i-1][j]);
else
t[i][j] = t[i-1][j];
}
}
return t[n][cap];
}
In the above, the wt[] can actually become the price of each item and favor-value is val[]. The cap needs to be modified to cap+200 but with some tricky checks which I couldn't figure out after trying for 2 days now. What modifications can I do here to take extra $200 for shopping above $2000. I tried many approaches but failed. I tried searching on internet but mostly there are recursive approaches used which I have already figured out or they have use space saving trick by using 1-D array. But I want to modify the classical solution to solve it, so as to improve and verify my understanding. Can some please give me a hint or direction.

Why should we use Dynamic Programming with Memoization in order to solve - Minimum Number of Coins to Make Change

The Problem Statement:
Given an infinite supply of coins of values {C1, C2, ..., Cn} and a sum, find the minimum number of coins that can represent the sum X.
Most of the solutions on the web include dynamic programming with memoization. Here is an example from Youtube: https://www.youtube.com/watch?v=Kf_M7RdHr1M
My question is: why don't we sort the array of coins in descending order first and start exploring recursively by minimizing the sum until we reach 0? When we reach 0, we know that we have found the needed coins to make up the sum. Because we sorted the array in descending order, we know that we will always choose the greatest coin. Therefore, the first time the sum reaches down to 0, the count will have to be minimum.
I'd greatly appreciate if you help understand the complexity of my algorithm and compare it to the dynamic programming with memoization approach.
For simplicty, we are assuming there will always be a "$1" coin and thus there is always a way to make up the sum.
import java.util.*;
public class Solution{
public static void main(String [] args){
MinCount cnt=new MinCount(new Integer []{1,2,7,9});
System.out.println(cnt.count(12));
}
}
class MinCount{
Integer[] coins;
public MinCount(Integer [] coins){
Arrays.sort(coins,Collections.reverseOrder());
this.coins=coins;
}
public int count(int sum){
if(sum<0)return Integer.MAX_VALUE;
if(sum==0)return 0;
int min=Integer.MAX_VALUE;
for(int i=0; i<coins.length; i++){
int val=count(sum-coins[i]);
if(val<min)min=val;
if(val!=Integer.MAX_VALUE)break;
}
return min+1;
}
}
Suppose that you have coins worth $1, $50, and $52, and that your total is $100. Your proposed algorithm would produce a solution that uses 49 coins ($52 + $1 + $1 + … + $1 + $1); but the correct minimum result requires only 2 coins ($50 + $50).
(Incidentally, I think it's cheating to write
For simplicty we are assuming there will always be a "$1" coin and thus there is always a way to make up the sum.
when this is not in the problem statement, and therefore not assumed in other sources. That's a bit like asking "Why do sorting algorithms always put a lot of effort into rearranging the elements, instead of just assuming that the elements are in the right order to begin with?" But as it happens, even assuming the existence of a $1 coin doesn't let you guarantee that the naïve/greedy algorithm will find the optimal solution.)
I will complement the answer that has already been provided to your question with some algorithm design advice.
The solution that you propose is what is called a "greedy algorithm": a problem solving strategy that makes the locally optimal choice at each stage with the hope of finding a global optimum.
In many problems, a greedy strategy does not produce an optimal solution. The best way to disprove the correctess of an algorithm is to find a counter-example, such as the case of the "$52", "$50", and "$1" coins. To find counter-examples, Steven Skiena gives the following advice in his book "The Algorithm Design Manual":
Think small: when an algorithm fails, there is usually a very simple example on which it fails.
Hunt for the weakness: if the proposed algorithm is of the form "always take the biggest" (that is, a greedy algorithm), think about why that might prove to be the wrong thing to do. In particular, ...
Go for a tie: A devious way to break a greedy algorithm is to provide instances where everything is the same size. This way the algorithm may have nothing to base its decision on.
Seek extremes: many counter-examples are mixtures of huge and tiny, left and right, few and many, near and far. It is usually easier to verify or reason about extreme examples than more muddled ones.
#recursive solution in python
import sys
class Solution:
def __init__(self):
self.ans=0
self.maxint=sys.maxsize-1
def minCoins(self, coins, m, v):
res=self.solve(coins,m,v)
if res==sys.maxsize-1:
return -1
return res
def solve(self,coins,m,v):
if m==0 and v>0:
return self.maxint
if v==0:
return 0
if coins[m-1]<=v:
self.ans=min(self.solve(coins,m,v-coins[m-1])+1,self.solve(coins,m-1,v))
return self.ans
else:
self.ans=self.solve(coins,m-1,v)
return self.ans

Instance of subset sum problem

I have a problem which is a pretty clear instance of the subset sum problem:
"given a list of Integers in the range [-65000,65000], the function returns true if any subset of the list summed is equal to zero. False otherwise."
What I wanted to ask is more of an explanation than a solution.
This was an instance-specific solution I came up before thinking about the complexity of the problem.
Sort the array A[] and, during sort, sum each element to a counter 'extSum' (O(NLogN))
Define to pointers low = A[0] and high = A[n-1]
Here is the deciding code:
while(A[low]<0){
sum = extSum;
if(extSum>0){
while(sum - A[high] < sum){
tmp = sum - A[high];
if(tmp==0) return true;
else if(tmp > 0){
sum = tmp;
high--;
}
else{
high--;
}
}
extSum -= A[low];
low++;
high = n - 1;
}
else{
/* Symmetric code: switch low, high and the operation > and < */
}
}
return false;
First of all, is this solution correct? I made some tests, but I am not sure...it looks too easy...
Isn't the time complexity of this code O(n^2)?
I already read the various DP solutions and the thing I would like to understand is, for the specific instance of the problem I am facing, how much better than this naive and intuitive solution they are. I know my approach can be improved a lot but nothing that would make a big difference when it comes to the time complexity....
Thank you for the clarifications
EDIT: One obvious optimization would be that, while sorting, if a 0 is found, the function returns true immediately....but it's only for the specific case in which there are 0s in the array.
Hmm, I think {0} will beat your answer.
Because it will simply ignore while and return false.

Algorithm to check if a number if a perfect number

I am looking for an algorithm to find if a given number is a perfect number.
The most simple that comes to my mind is :
Find all the factors of the number
Get the prime factors [except the number itself, if it is prime] and add them up to check if it is a perfect number.
Is there a better way to do this ?.
On searching, some Euclids work came up, but didnt find any good algorithm. Also this golfscript wasnt helpful: https://stackoverflow.com/questions/3472534/checking-whether-a-number-is-mathematically-a-perfect-number .
The numbers etc can be cached etc in real world usage [which I dont know where perfect nos are used :)]
However, since this is being asked in interviews, I am assuming there should be a "derivable" way of optimizing it.
Thanks !
If the input is even, see if it is of the form 2^(p-1)*(2^p-1), with p and 2^p-1 prime.
If the input is odd, return "false". :-)
See the Wikipedia page for details.
(Actually, since there are only 47 perfect numbers with fewer than 25 million digits, you might start with a simple table of those. Ask the interviewer if you can assume you are using 64-bit numbers, for instance...)
Edit: Dang, I failed the interview! :-(
In my over zealous attempt at finding tricks or heuristics to improve upon the "factorize + enumerate divisors + sum them" approach, I failed to note that being 1 modulo 9 was merely a necessary, and certainly not a sufficient condition for at number (other than 6) to be perfect...
Duh... with on average 1 in 9 even number satisfying this condition, my algorithm would sure find a few too many perfect numbers ;-).
To redeem myself, persist and maintain the suggestion of using the digital root, but only as a filter, to avoid the more expensive computation of the factor, in most cases.
[Original attempt: hall of shame]
If the number is even,<br>
compute its [digital root][1].
if the digital root is 1, the number is perfect, otherwise it isn't.
If the number is odd...
there are no shortcuts, other than...
"Not perfect" if the number is smaller than 10^300
For bigger values, one would then need to run the algorithm described in
the question, possibly with a few twists typically driven by heuristics
that prove that the sum of divisors will be lacking when the number
doesn't have some of the low prime factors.
My reason for suggesting the digital root trick for even numbers is that this can be computed without the help of an arbitrary length arithmetic library (like GMP). It is also much less computationally expensive than the decomposition in prime factors and/or the factorization (2^(p-1) * ((2^p)-1)). Therefore if the interviewer were to be satisfied with a "No perfect" response for odd numbers, the solution would be both very efficient and codable in most computer languages.
[Second and third attempt...]
If the number is even,<br>
if it is 6
The number is PERFECT
otherwise compute its [digital root][1].
if the digital root is _not_ 1
The number is NOT PERFECT
else ...,
Compute the prime factors
Enumerate the divisors, sum them
if the sum of these divisor equals the 2 * the number
it is PERFECT
else
it is NOT PERFECT
If the number is odd...
same as previously
On this relatively odd interview question...
I second andrewdski's comment to another response in this post, that this particular question is rather odd in the context of an interview for a general purpose developer. As with many interview questions, it can be that the interviewer isn't seeking a particular solution, but rather is providing an opportunity for the candidate to demonstrate his/her ability to articulate the general pros and cons of various approaches. Also, if the candidate is offered an opportunity to look-up generic resources such as MathWorld or Wikipedia prior to responding, this may also be a good test of his/her ability to quickly make sense of the info offered there.
Here's a quick algorithm just for fun, in PHP - using just a simple for loop. You can easliy port that to other languages:
function isPerfectNumber($num) {
$out = false;
if($num%2 == 0) {
$divisors = array(1);
for($i=2; $i<$num; $i++) {
if($num%$i == 0)
$divisors[] = $i;
}
if(array_sum($divisors) == $num)
$out = true;
}
return $out ? 'It\'s perfect!' : 'Not a perfect number.';
}
Hope this helps, not sure if this is what you're looking for.
#include<stdio.h>
#include<stdlib.h>
int sumOfFactors(int );
int main(){
int x, start, end;
printf("Enter start of the range:\n");
scanf("%d", &start);
printf("Enter end of the range:\n");
scanf("%d", &end);
for(x = start;x <= end;x++){
if(x == sumOfFactors(x)){
printf("The numbers %d is a perfect number\n", x);
}
}
return 0;
}
int sumOfFactors(int x){
int sum = 1, i, j;
for(j=2;j <= x/2;j++){
if(x % j == 0)
sum += j;
}
return sum;
}

What is a typical algorithm for finding a string within a string?

I recently had an interview question that went something like this:
Given a large string (haystack), find a substring (needle)?
I was a little stumped to come up with a decent solution.
What is the best way to approach this that doesn't have a poor time complexity?
I like the Boyer-Moore algorithm. It's especially fun to implement when you have a lot of needles to find in a haystack (for example, probable-spam patterns in an email corpus).
You can use the Knuth-Morris-Pratt algorithm, which is O(n+m) where n is the length of the "haystack" string and m is the length of the search string.
The general problem is string searching; there are many algorithms and approaches depending on the nature of the application.
Knuth-Morris-Pratt, searches for a string within another string
Boyer-Moore, another string within string search
Aho-Corasick; searches for words from a reference dictionary in a given arbitrary text
Some advanced index data structures are also used in other applications. Suffix trees are used a lot in bioinformatics; here you have one long reference text, and then you have many arbitrary strings that you want to find all occurrences for. Once the index (i.e. the tree) is built, finding patterns can be done quite efficiently.
For an interview answer, I think it's better to show breadth as well. Knowing about all these different algorithms and what specific purposes they serve best is probably better than knowing just one algorithm by heart.
I do not believe that there is anything better then looking at the haystack one character at a time and try to match them against the needle.
This will have linear time complexity (against the length of the haystack). It could degrade if the needle is near the same length as the haystack and shares a long common and repeated prefix.
A typical algorithm would be as follows, with string indexes ranging from 0 to M-1.
It returns either the position of the match or -1 if not found.
foreach hpos in range 0 thru len(haystack)-len(needle):
found = true
foreach npos in range 0 thru len(needle):
if haystack[hpos+npos] != needle[npos]:
found = false
break
if found:
return hpos
return -1
It has a reasonable performance since it only checks as many characters in each haystack position as needed to discover there's no chance of a match.
It's not necessarily the most efficient algorithm but if your interviewer expects you to know all the high performance algorithms off the top of your head, they're being unrealistic (i.e., fools). A good developer knows the basics well, and how to find out the advanced stuff where necessary (e.g., when there's a performance problem, not before).
The performance ranges between O(a) and O(ab) depending on the actual data in the strings, where a and b are the haystack and needle lengths respectively.
One possible improvement is to store, within the npos loop, the first location greater than hpos, where the character matches the first character of the needle.
That way you can skip hpos forward in the next iteration since you know there can be no possible match before that point. But again, that may not be necessary, depending on your performance requirements. You should work out the balance between speed and maintainability yourself.
This problem is discussed in Hacking a Google Interview Practice Questions – Person A. Their sample solution:
bool hasSubstring(const char *str, const char *find) {
if (str[0] == '\0' && find[0] == '\0')
return true;
for(int i = 0; str[i] != '\0'; i++) {
bool foundNonMatch = false;
for(int j = 0; find[j] != '\0'; j++) {
if (str[i + j] != find[j]) {
foundNonMatch = true;
break;
}
}
if (!foundNonMatch)
return true;
}
return false;
}
Here is a presentation of a few algorithm (shamelessly linked from Humboldt University). contains a few good algorithms such as Boyer More and Z-box.
I did use the Z-Box algorithm, found it to work well and was more efficient than Boyer-More, however needs some time to wrap your head around it.
the easiest way I think is "haystack".Contains("needle") ;)
just fun,dont take it seriously.I think already you have got your answer.

Resources