Find text path through character matrix with recursive algorithm - algorithm

I'm trying to solve this question: http://www.spoj.com/problems/ALLIZWEL/
Find whether there is a path in the given matrix which makes the
sentence “ALL IZZ WELL”.
There is a path from any cell to all its neighbouring cells.
A neighbour may share an edge or a corner.
Input Specification:
The first line consists of an integer t representing the number of test cases.
The first line of each test
case consists of two integers R and C representing the number of rows and number of columns in the matrix.
Output Specification:
For each test case print “YES” if there is a path which makes the sentence “ALLIZZWELL”.
Else print “NO”.
For sample test cases, open the link.
My code:
#include <iostream>
#include <map>
#include <vector>
#include <string>
#include <utility>
#include <algorithm>
#include <stack>
#include <queue>
#include <climits>
#include <set>
using namespace std;
char matrix[101][101];
bool var;
int r,c;
bool check (string str,int pos, bool visited[101][101],int i, int j);
int main (void)
{
int t,i,j;
cin>>t;
bool ans;
while (t != 0)
{
int r,c,flag=0;
cin>>r>>c;
for ( i = 0; i < r; i++ )
{
for ( j = 0; j < c; j++ )
{
cin>>matrix[i][j];
}
}
string str = "ALLIZZWELL";
int pos = 1;
for ( i = 0; i < r; i++ )
{
for ( j = 0; j < c; j++ )
{
bool visited[101][101];
for ( i = 0; i < 101; i++ )
for ( j = 0; j < 101; j++ )
visited[i][j] = false;
visited[i][j] = true;
if (matrix[i][j] == 'A') // for all possible starting positions
ans = check(str,pos,visited,i,j);
if (ans == true)
{
cout<<"YES\n";
flag = 1;
break;
}
if (flag == 1)
break;
}
}
if (flag == 0)
cout<<"NO\n";
t--;
}
return 0;
}
bool check (string str,int pos, bool visited[101][101],int i, int j) // checking for all possible test cases
{
bool result = false;
if (pos == str.length() + 1)
return true;
if (i+1 < r && visited[i+1][j] != true && matrix[i+1][j] == str[pos])
{
visited[i+1][j] = true;
result = result || check(str,pos+1,visited,i+1,j);
if (result == false)
visited[i+1][j] = false;
}
else if (i-1 >= 0 && visited[i-1][j] != true && matrix[i-1][j] == str[pos])
{
visited[i-1][j] = true;
result = result || check(str,pos+1,visited,i-1,j);
if (result == false)
visited[i-1][j] = true;
}
else if (j+1 < c && visited[i][j+1] != true && matrix[i][j+1] == str[pos])
{
visited[i][j+1] = true;
result = result || check(str,pos+1,visited,i,j+1);
if (result == false)
visited[i][j+1] = true;
}
else if (j-1 >= 0 && visited[i][j-1] != true && matrix[i][j-1] == str[pos])
{
visited[i][j-1] = true;
result = result || check(str,pos+1,visited,i,j-1);
if (result == false)
visited[i][j-1] = true;
}
else if (i+1 < r && j+1 < c && visited[i+1][j+1] != true && matrix[i+1][j+1] == str[pos])
{
visited[i+1][j+1] = true;
result = result || check(str,pos+1,visited,i+1,j+1);
if (result == false)
visited[i+1][j+1] = true;
}
else if (i+1 < r && j-1 >= 0 && visited[i+1][j-1] != true && matrix[i+1][j-1] == str[pos])
{
visited[i+1][j-1] = true;
result = result || check(str,pos+1,visited,i+1,j-1);
if (result == false)
visited[i+1][j-1] = true;
}
else if (i-1 >= 0 && j+1 < c && visited[i-1][j+1] != true && matrix[i-1][j+1] == str[pos])
{
visited[i-1][j+1] = true;
result = result || check(str,pos+1,visited,i-1,j+1);
if (result == false)
visited[i-1][j+1] = true;
}
else if (i-1 >= 0 && j-1 >= 0 && visited[i-1][j-1]!= true && matrix[i-1][j-1] == str[pos])
{
visited[i-1][j-1] = true;
result = result || check(str,pos+1,visited,i-1,j-1);
if (result == false)
visited[i-1][j-1] = true;
}
return false;
}
The code is quite self-explanatory: I am trying all possible cases.
I am getting a WA in the third test case, i.e.
2 9
A.L.Z.E..
.L.I.W.L.
I tried debugging but I couldn't narrow down my problem.

The main problems are:
Using i and j in the loop clearing visited (as well as the outer loops)
Using r and c as global variables in check, but writing them as local variables in main
Always returning false from check (instead of result)
Only trying the first choice in check (turn "else if" into "if")
Not clearing the value in ans
Only breaking out of the inner loop, not both the i and j loop
Terminating the search when pos gets to str.length()+1 instead of str.length()
It often helps to put some print statements in recursive functions like these, try them out on a simple example, and see whether the sequence of calls matches your expectations.

Related

Why my dfs code is not working in word search problem?

**this solution is always return 0 My idea is I traverse dfs in four sides and check the condition **```
#include<bits/stdc++.h>
using namespace std;
// } Driver Code Ends
class Solution {
public:
bool dfs(int i,int j,int idx,vector<vector> & board, string & word,vector<vector> & vis
,int del_row[],int del_col[]){
if(idx == word.size()){
return true;
}
vis[i][j]=1;
int n = board.size();
int m = board[0].size();
for(int k=0;k< 4 ;k++){
int row = i + del_row[k];
int col = j + del_col[k];
if( row >= 0 && col >= 0 && row < n && col < m && vis[i][j]== 0 &&
board[row][col] == word[idx]){
if(dfs(row,col,idx+1,board,word,vis,del_row,del_col)){
return true;
}
}
}
vis[i][j] =0;
return false;
}
bool isWordExist(vector<vector<char>>& board, string word) {
// Code here
int n = board.size();
int m = board[0].size();
vector<vector<int>> vis(n,vector<int>(m,0));
int del_row [] = {-1,+1,0,0};
int del_col [] = {0,0,-1,+1};
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(board[i][j] == word[0] && !vis[i][j]){
if(dfs(i,j,1,board,word,vis,del_row,del_col)){
return true;
}
}
}
}
return false;
}
};
this code is always return 0 .

Special minimum spanning tree

There is a node that can only get one line, I use both kruskal and prim, but the judger said TLE(Time Limit Exceed).
Then I will describe the question. There are many computers, we need to connect all of them, we give the cost of connection between different computers, also we give the special number of computer which can be only connected by one line. Finally, we guarantee there is a answer and there is no Self-Loop, but there may have multiple edge which have different weight between same node.
Here is my kruskal code, it's TLE.
#include <iostream>
#include <algorithm>
using namespace std;
typedef struct edge{
int start;
int end;
int weight;
}Edge;
int special = 0;
int edgenum;
Edge _edge[600005];
int i, j, k;
int counter = 0;
bool Cmp(const edge &a, const edge &b){
return a.weight < b.weight;
}
int getEnd(int vends[], int i){
while(vends[i] != 0)
i = vends[i];
return i;
}
void kruskal(){
int p1, p2, m, n, ans = 0;
int vends[10005] = {0};
sort(_edge, _edge+counter, Cmp);
for(i = 0; i < edgenum; ++i){
p1 = _edge[i].start;
p2 = _edge[i].end;
if ((p1 == k || p2 == k) && special)
continue;
m = getEnd(vends, p1);
n = getEnd(vends, p2);
if(m != n){
if (p1 == k || p2 == k)
special = 1;
vends[m] = n;
ans += _edge[i].weight;
}
}
cout << ans << endl;
}
int main(){
int n, m;
cin >> n >> m >> k;
edgenum = m;
while(m--){
int a, b, c;
cin >> a >> b >> c;
_edge[counter].start = a; //Get the Edge
_edge[counter].weight = c;
_edge[counter++].end = b;
// _edge[counter].start = b;
// _edge[counter].weight = c;
// _edge[counter++].end = a;
}
kruskal();
}
Here is my Prim, but also TLE:
#include <iostream>
using namespace std;
typedef char VertexType;
typedef struct node{
int adjvex = 0;
int weight = INT32_MAX;
struct node *next = NULL;
}Node;
typedef struct vnode{
VertexType data;
Node *firstnode = NULL;
}Vnode;
Vnode node[10005];
int VNUM;
int n, m, k;
int lowcost[10005] = {0};
int addvnew[10005]; //未加入最小生成树表示为-1,加入则为0
int adjecent[10005] = {0};
bool is_special = false;
int flag;
void prim(int start){
long long sumweight = 0;
int i, j;
Node *p = node[start].firstnode;
for (i = 1; i <= VNUM; ++i) { //重置
addvnew[i] = -1;
}
while (p->next != NULL){
if (lowcost[p->adjvex] == 0 || p->weight < lowcost[p->adjvex])
lowcost[p->adjvex] = p->weight;
p = p->next;
}
if (lowcost[p->adjvex] == 0 || p->weight < lowcost[p->adjvex])
lowcost[p->adjvex] = p->weight;
addvnew[start] = 0;
// adjecent[start] = start;
if (start == k) {
is_special = true;
flag = 1;
}
for (i = 1; i < VNUM; ++i) {
int min = INT32_MAX;
int v=-1;
for (j = 1; j <= VNUM; ++j) { //Find the min
if (addvnew[j] == -1 && lowcost[j] < min && lowcost[j] != 0){
min = lowcost[j];
v = j;
}
}
if (v != -1){ //if min is found
if (flag == 1){
for (int l = 0; l < 10005; ++l) {
lowcost[l] = 0;
}
flag = 0;
}
addvnew[v] = 0;
sumweight += min;
p = node[v].firstnode;
while(p->next != NULL){
if (is_special && p->adjvex == k){ //If find the special node
p = p->next;
continue;
}
if(addvnew[p->adjvex] == -1 && (lowcost[p->adjvex] == 0 || p->weight < lowcost[p->adjvex])){ //如果该点未连接
lowcost[p->adjvex] = p->weight;
}
p = p->next;
}
if (!(is_special && p->adjvex == k))
if(addvnew[p->adjvex] == -1 && (lowcost[p->adjvex] == 0 || p->weight < lowcost[p->adjvex])){
lowcost[p->adjvex] = p->weight;
}
}
}
cout << sumweight << endl;
}
int main(){
cin >> n >> m >> k;
VNUM = n;
while (m--){
int a, b, c;
cin >> a >> b >> c;
Node *p = (Node*)malloc(sizeof(Node));
p->adjvex = b;
p->weight = c;
p->next = node[a].firstnode;
node[a].firstnode = p;
Node *q = (Node*)malloc(sizeof(Node));
q->adjvex = a;
q->weight = c;
q->next = node[b].firstnode;
node[b].firstnode = q;
}
prim(k);
}
I don't know how to modify the both code, I try my best, thank you

How to step over a recursive call while debugging?

I have tried in two IDEs namely Clion and Xcode and I get the same results.
The debugger steps into isMatch function again even if I use stepOver. I've successfully used 'stepOver' in case of other functions but I'm not sure if it works the expected way for recursive calls. Can someone help me with this?
bool isMatch(string s, string p) {
//Base case
if(s.length() == 0 && p.length() == 0)
return true;
else if(p[1] == '*') {
int i = 0;
for (; (s[i] == p[0] || p[0] == '.') && i<s.length() ; i++) {
string temp1 = s.substr(i);
string temp2 = !p.length()? "" : p.substr(2);
if (isMatch(temp1, temp2))
return true;
}
if( isMatch(s.substr(i), !p.length()? "" : p.substr(2) ))
return true;
return false;
}
else
return (s[0] == p[0] || p[0] == '.') && isMatch(s.substr(1), p.substr(1));
}

For a given string which contains only digits , what's the optimal approach to return all valid ip address combinations?

Example:
Given “25525511135”
Output : [“255.255.11.135”, “255.255.111.35”]. (sorted order)
Kindly let me know if we could do a depth first search over here ?(that's the only thing striking me )
Why is it important to have an 'optimal' approach for answering this?
There are not many permutations so the simple approach of checking every combination that fits into the IP format and then filtering out those that have out of range numbers will easily work.
It's unlikely to be a bottle neck for whatever this is part of.
You probably want a dynamic programming algorithm for the general case (something like
http://www.geeksforgeeks.org/dynamic-programming-set-32-word-break-problem/).
Instead of testing whether prefixes can be segmented into words in the dictionary, you'd be testing to see whether the prefixes are prefixes of some valid IPv4 address.
Brutal DFS is acceptable in this problem:
class Solution{
private:
vector<string> ans;
int len;
string cur, rec, str;
bool IsOk(string s) {
if(s[0] == '0' && s.size() > 1) return false;
int sum = 0;
for(int i = 0; i < s.size(); i ++) {
if(s[i] == '.') return false;
sum = sum * 10 + s[i] - '0';
}
if(sum >= 0 && sum <= 255) return true;
return false;
}
void dfs(int x, int cnt) {
if(x == len) {
if(str.size() != len + 4) return ;
string tmp(str);
tmp.erase(tmp.size() - 1, 1);
if(cnt == 4) ans.push_back(tmp);
return ;
}
if(cnt > 4 || str.size() > len + 4) return ;
string tmp = cur;
cur += rec[x];
if(!IsOk(cur)) {
cur = tmp;
return ;
}
dfs(x + 1, cnt);
string tmp2 = cur + '.';
str += tmp2;
cur = "";
dfs(x + 1, cnt + 1);
str.erase(str.size() - tmp2.size(), tmp2.size());
cur = tmp;
}
public:
vector<string> restoreIpAddresses(string s) {
this->len = s.size();
this->rec = s;
cur = str = "";
ans.clear();
dfs(0, 0);
return ans;
}
};
Here is a recursive solution on JavaScript. The result is not sorted.
// Task from https://www.geeksforgeeks.org/program-generate-possible-valid-ip-addresses-given-string/
// Given a string containing only digits, restore it by returning all possible valid IP address combinations.
//
// Example:
// Input : 25525511135
// Output : [“255.255.11.135”, “255.255.111.35”]
//
(function () {
function getValidIP(str) {
const result = [];
const length = str.length;
check(0, 0, '');
function check(start, level, previous){
let i = 0;
let num;
if (level === 3) {
num = str.substring(start);
if (num && num < 256) {
result.push(`${previous}.${num}`);
}
return;
}
num = str.substring(start, start + 1);
if (num == 0) {
check(start + 1, level + 1, level === 0 ? `${num}`: `${previous}.${num}`);
} else {
while (num.length < 4 && num < 256 && start + i + 1 < length) {
check(start + i + 1, level + 1, level === 0 ? `${num}`: `${previous}.${num}`);
i++;
num = str.substring(start, start + i + 1);
}
}
}
return result;
}
console.log('12345:')
console.time('1-1');
console.log(getValidIP('12345'));
console.timeEnd('1-1');
console.log('1234:')
console.time('1-2');
console.log(getValidIP('1234'));
console.timeEnd('1-2');
console.log('2555011135:')
console.time('1-3');
console.log(getValidIP('2555011135'));
console.timeEnd('1-3');
console.log('222011135:')
console.time('1-4');
console.log(getValidIP('222011135'));
console.timeEnd('1-4');
})();

Dynamic Programming Altogorithm

I'm trying to construct an algorithm that runs at O(nb) time with the following input/question:
input: an array A[1..n] of n different integers and an integer b (i am assuming that the numbers in A are sequential, starting at 1 ending at n, i.e. for n=4 A[1,2,3,4].
question: in how many ways can b be written as the sum of elements of the array when elements in A[] can only be used once?
I've kind of hit a wall on this one. I'm looking for some kind of recursive solution, but I don't see how to avoid using repeat numbers. Like, for instance, if we started at 1 and stored all the ways to make one (just 1) then 2 (just 2) then three (3 or 2+1) etc, it shouldn't be hard to see how many ways we can make larger numbers. But if, for instance, we take 5, we will see that it can be broken into 4+1, and 4 can be further broken down into 3+1, so then we would see 2 solutions (4+1, and 3+1+1), but one of those has a repeat of a number. Am I missing something obvious? Thanks so much!
Recursive and dynamic solutions in C:
#include <stddef.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
typedef unsigned char uchar;
typedef unsigned int uint;
typedef struct tAddend
{
struct tAddend* pPrev;
uint Value;
} tAddend;
void findRecursiveSolution(uint n, uint maxAddend, tAddend* pPrevAddend)
{
uint i;
for (i = maxAddend; ; i--)
{
if (n == 0)
{
while (pPrevAddend != NULL)
{
printf("+%u", pPrevAddend->Value);
pPrevAddend = pPrevAddend->pPrev;
}
printf("\n");
return;
}
if (n >= i && i > 0)
{
tAddend a;
a.pPrev = pPrevAddend;
a.Value = i;
findRecursiveSolution(n - i, i - 1, &a);
}
if (i <= 1)
{
break;
}
}
}
void printDynamicSolution(uchar** pTable, uint n, uint idx, uint sum, tAddend* pPrevAddend)
{
uchar el = pTable[idx][sum];
assert((el != 0) && (el != 5) && (el != 7));
if (el & 2) // 2,3,6 - other(s)
{
printDynamicSolution(pTable,
n,
idx - 1,
sum,
pPrevAddend);
}
if (el & 4) // self + other(s)
{
tAddend a;
a.pPrev = pPrevAddend;
a.Value = idx + 1;
printDynamicSolution(pTable,
n,
idx - 1,
sum - (idx + 1),
&a);
}
if (el & 1) // self, found a solution
{
tAddend a;
a.pPrev = pPrevAddend;
a.Value = idx + 1;
pPrevAddend = &a;
while (pPrevAddend != NULL)
{
printf("+%u", pPrevAddend->Value);
pPrevAddend = pPrevAddend->pPrev;
}
printf("\n");
}
}
void findDynamicSolution(uint n)
{
uchar** table;
uint i, j;
if (n == 0)
{
return;
}
// Allocate the DP table
table = malloc(sizeof(uchar*) * n);
if (table == NULL)
{
printf("not enough memory\n");
return;
}
for (i = 0; i < n; i++)
{
table[i] = malloc(n + 1);
if (table[i] == NULL)
{
while (i > 0)
{
free(table[--i]);
}
free(table);
printf("not enough memory\n");
return;
}
}
// Fill in the DP table
for (i = 0; i < n; i++)
{
for (j = 0; j <= n; j++)
{
if (i == 0)
{
table[i][j] = (i + 1 == j); // self
}
else
{
table[i][j] = (i + 1 == j) + // self
2 * (table[i - 1][j] != 0) + // other(s)
4 * ((j >= i + 1) && (table[i - 1][j - (i + 1)] != 0)); // self + other(s)
}
}
}
printDynamicSolution(table, n, n - 1, n, NULL);
for (i = 0; i < n; i++)
{
free(table[i]);
}
free(table);
}
int main(int argc, char** argv)
{
uint n;
if (argc != 2 || sscanf(argv[1], "%u", &n) != 1)
{
n = 10;
}
printf("Recursive Solution:\n");
findRecursiveSolution(n, n, NULL);
printf("\nDynamic Solution:\n");
findDynamicSolution(n);
return 0;
}
Output:
for 10:
Recursive Solution:
+10
+1+9
+2+8
+3+7
+1+2+7
+4+6
+1+3+6
+1+4+5
+2+3+5
+1+2+3+4
Dynamic Solution:
+1+2+3+4
+2+3+5
+1+4+5
+1+3+6
+4+6
+1+2+7
+3+7
+2+8
+1+9
+10
See also on ideone.
Let F(x,i) be the number of ways elements of A[1:i] can be summed to get x.
F(x,i+1) = F(x-A[i+1],i) + F(x,i)
That is it!
This is not a dynamic programming solution though. Non-recursive.
Assumption that arr is sorted in your case like [i....j] where a[i] <= a[j]
That's easy enough
void summer(int[] arr, int n , int b)
{
int lowerbound = 0;
int upperbound = n-1;
while (lowerbound < upperbound)
{
if(arr[lowerbound]+arr[upperbound] == b)
{
// print arr[lowerbound] and arr[upperbound]
lowerbound++; upperbound--;
}
else if(arr[lowerbound]+arr[upperbound] < b)
lowerbound++;
else
upperbound--;
}
}
The above program is easily modifiable to a recursive you need to only change the function definition by passing lowerbound and upperbound.
Case for termination is still lowerbound < upperbound
Base case is if arr[lowerbound] +arr[upperbound] == b
Edited based on comments
You will need to use a modified version of integer knapsack problem. The values of [i,j] both need to be modified accordingly. You are having the problem because you are not most probably modifying your i carefully, Increase your i accordingly then their will not be repetition like the one you are having.

Resources