Open In App

Samsung Semiconductor Institute of Research(SSIR Software) intern/FTE | Set-3

Last Updated : 05 Sep, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

We are given m*n matrix which can have a number between 0 and 7. Each number represents a pipe with a shape as follows: 

Pipes

Two pipes are considered connected if their end points connect. 

Example: 

If matrix is as follows: 
0040 
1360 
5000 

Pipe 1 and 3{1 opens to right. 3 opens to left} are connected. Other connected pipes are 3 and 6(3 opens to right. 6 opens to left). 
4 and 6 are not connected as 6 does not open to top, and 4 does not open to bottom. 
1 and 5 are also not connected as even though 1 opens to bottom, 5 is not open to top.

Given this matrix, start point (X, Y) and length of probe tool “L”, find out how many pipes{matrix elements} can be reached. 

Note: Probe tool: is a measuring tool, if 6 pipes can be reached but length of probe tool is 4. Answer will be 4 if 3 pipes can be reached but length of probe tool is 4. Answer will be 3.

Example: 

Starting index: (1, 0) , Length of probe: 4 

Matrix: 
              {0040 
              1360 
             5000} 

connected pipes via probe- (1, 0)->(1, 1)->(1, 2) 
Ans- 3

Starting index: (0, 0) , Length of probe: 4 

Matrix: 
            {0040 
             1360 
            5000} 
connected pipes via probe- 0 
Ans- 0

Starting index: (1, 0) , Length of probe: 2 

Matrix: 
             {0040 
             1360 
             5000 }
connected pipes via probe- (1, 0)->(1, 1) 
Ans- 2

Key Steps to solve: 

Find which of the neighboring pipe elements can be accessed from one starting point {Maintaining exhaustive list of checks to ascertain neighboring criteria as defined above}. 
Find a method to process through the elements to find the next set of elements which can be accessed. {Traversing through the graph}. It should be noted that we wish to reach all nodes which are accessible from start node with distance less than “L”. The focus is not on reaching lot of nodes, but on reaching them with lesser moves from start point (X, Y). 

Recursion: 

We mark all the nodes as unvisited and visited node count as 0. If a node marked as unvisited is processed during recursion, increment visited node count by 1 and mark it as visited. 
We start by visiting Start node (X, Y) and then recursively visiting all its connected neighbors (based on checks for connected criteria as defined above) till the recursion depth of “L”. 

Drawback: 

In case of highly connected matrix (almost all pipes are connected together and multiple ways to reach a pipe exists), we reach a node multiple times and process it multiple times which may lead to high running time. We can optimize it by checking that we process a node again only if we have reached it with a lower recursion level. 
This is not a DFS solution because we reprocess a node, even if already visited, as it is possible that the new visit may update the visiting depth of the node to lower level and greater depth be reached after this node. 

Breadth-First Search: 

We mark all the nodes as unvisited and visited node count as 0. If a node marked as unvisited is processed during processing, increment visited node count by 1. 
We start by pushing the start node (X, Y) into a queue with depth 1 and then start processing the queue till it is empty. 
In each iteration a member of queue is taken out and its connected neighbors are analyzed. If neighbors are unvisited and depth of current element is not greater than L, connected elements are put into queue, marked visited and visited node count increased by 1. 
As BFS performs level order traversal of nodes, it is not possible that a visited node be reached in a smaller distance. So, drawback of previous method cannot exist. This is the optimal solution for this problem. 

Simplification possible in the solutions for easy coding: 

Since there are 7 types of pipes, we will have to put multiple if conditions leading to nested if statements which are difficult to debug. It can be simplified by converting the 7 values into direction based data. For e.g. each value can be transformed into a structure with 4 Boolean variables, one for each direction. Alternatively, each number can be mapped to a 4 bit number where each bit represents a direction. After this input reduction, checks will become simpler and with less complexity. 

Implementation:

C++




#include <bits/stdc++.h>
using namespace std;
#define Max 1000
#define row_size 3
#define col_size 4
 
int x = 1, y = 0; // starting index(x, y),
int l = 4; // length of probe tool
 
// input matrix containing the pipes
int mt[row_size][col_size] = { { 0, 0, 4, 0 },
                               { 1, 3, 6, 0 },
                               { 5, 0, 0, 0 } };
 
// visited matrix checks for cells already visited
int vi[row_size][col_size];
 
// calculates the depth of connection for each cell
int depth[row_size][col_size];
 
int f = 0;
int r = 0;
 
// queue for BFS
struct node {
    int x;
    int y;
    int d;
};
node q[Max];
void push(int a, int b, int d) // push function
{
    node temp;
    temp.x = a;
    temp.y = b;
    temp.d = d;
    q[r++] = temp;
    vi[a][b] = 1;
}
node pop() // pop function
{
    node temp;
    temp.x = q[f].x;
    temp.y = q[f].y;
    temp.d = q[f].d;
    f++;
    return temp;
}
 
// It can be simplified by converting the 7
// values into direction based data. For e.g.
// each value can be transformed into a structure
// with 4 Boolean variables, one for each direction.
// Alternatively, each number can be mapped to a 4
// bit number where each bit represents a direction.
bool s1(int i, int j) // conversion to final direction
{
    if (i >= 0 && i < row_size && j >= 0 &&
        j < col_size && vi[i][j] == 0 && (mt[i][j] == 1 ||
        mt[i][j] == 3 || mt[i][j] == 6 || mt[i][j] == 7))
        return true;
    else
        return false;
}
 
bool s2(int i, int j) // conversion to final direction
{
    if (i >= 0 && i < row_size && j >= 0 && j < col_size &&
        vi[i][j] == 0 && (mt[i][j] == 1 || mt[i][j] == 2 ||
        mt[i][j] == 4 || mt[i][j] == 7))
        return true;
    else
        return false;
}
bool s3(int i, int j) // conversion to final direction
{
    if (i >= 0 && i < row_size && j >= 0 && j < col_size &&
        vi[i][j] == 0 && (mt[i][j] == 1 || mt[i][j] == 3 ||
        mt[i][j] == 4 || mt[i][j] == 5))
        return true;
    else
        return false;
}
bool s4(int i, int j) // conversion to final direction
{
    if (i >= 0 && i < row_size && j >= 0 && j < col_size &&
       vi[i][j] == 0 && (mt[i][j] == 1 || mt[i][j] == 2 ||
       mt[i][j] == 6 || mt[i][j] == 5))
        return true;
    else
        return false;
}
 
// search for connection
// We start by pushing the start node (X, Y) into a queue
// with depth 1  and then start processing the queue till
// it is empty.
void bfs(int x, int y, int d)
{
    push(x, y, d);
    while (r > f) {
        node temp = pop();
        int i = temp.x;
        int j = temp.y;
        int c = temp.d;
        depth[i][j] = c;
 
        if (mt[i][j] == 1 || mt[i][j] == 3 ||
            mt[i][j] == 4 || mt[i][j] == 5) {
            if (s1(i, j + 1))
                push(i, j + 1, c + 1);
        }
        if (mt[i][j] == 1 || mt[i][j] == 2 ||
            mt[i][j] == 6 || mt[i][j] == 5) {
            if (s2(i + 1, j))
                push(i + 1, j, c + 1);
        }
        if (mt[i][j] == 1 || mt[i][j] == 3 ||
            mt[i][j] == 7 || mt[i][j] == 6) {
            if (s3(i, j - 1))
                push(i, j - 1, c + 1);
        }
        if (mt[i][j] == 1 || mt[i][j] == 2 ||
            mt[i][j] == 4 || mt[i][j] == 7) {
            if (s4(i - 1, j))
                push(i - 1, j, c + 1);
        }
    }
}
int main() // main function
{
 
    f = 0;
    r = 0;
    // matrix
    for (int i = 0; i < row_size; i++) {
        for (int j = 0; j < col_size; j++) {
 
            // visited matrix for BFS set to
            // unvisited for every cell
            vi[i][j] = 0;
 
            // depth set to max initial value
            depth[i][j] = Max;
        }
    }
 
    if (mt[x][y] != 0) // condition for BFS
        bfs(x, y, 1);
 
    int nc = 0;
    for (int i = 0; i < row_size; i++) {
        for (int j = 0; j < col_size; j++) {
            if (depth[i][j] <= l) {
                cout << "(" << i << ", " << j << ")";
                nc++;
            }
        }
    }
    cout << " " << nc << "\n";
}


Python3




Max=1000
row_size=3
col_size=4
 
x = 1; y = 0 # starting index(x, y),
l = 4 # length of probe tool
 
# input matrix containing the pipes
mt = [[ 0, 0, 4, 0 ,],
                               [ 1, 3, 6, 0],
                               [ 5, 0, 0, 0],]
 
# visited matrix checks for cells already visited
vi=[[False for _ in range(col_size)]for _ in range(row_size)]
 
# calculates the depth of connection for each cell
depth=[[0 for _ in range(col_size)] for _ in range(row_size)]
 
f = 0
r = 0
 
# queue for BFS
class node:
    def __init__(self,x,y,d):
        self.x=x
        self.y=y
        self.d=d
 
q=[None for _ in range(Max)]
def push(a, b, d): # push function
    global r
    temp=node(a,b,d)
    q[r] = temp
    r+=1
    vi[a][b] = 1
 
def pop(): # pop function
    global f
    temp=node(q[f].x,q[f].y,q[f].d)
    f+=1
    return temp
 
 
# It can be simplified by converting the 7
# values into direction based data. For e.g.
# each value can be transformed into a structure
# with 4 Boolean variables, one for each direction.
# Alternatively, each number can be mapped to a 4
# bit number where each bit represents a direction.
def s1(i, j): # conversion to final direction
    if (i >= 0 and i < row_size and j >= 0 and
        j < col_size and vi[i][j] == 0 and (mt[i][j] == 1 or
        mt[i][j] == 3 or mt[i][j] == 6 or mt[i][j] == 7)):
        return True
    else:
        return False
 
 
def s2(i, j): # conversion to final direction
 
    if (i >= 0 and i < row_size and j >= 0 and j < col_size and
        vi[i][j] == 0 and (mt[i][j] == 1 or mt[i][j] == 2 or
        mt[i][j] == 4 or mt[i][j] == 7)):
        return True
    else:
        return False
 
def s3(i, j): # conversion to final direction
    if (i >= 0 and i < row_size and j >= 0 and j < col_size and
        vi[i][j] == 0 and (mt[i][j] == 1 or mt[i][j] == 3 or
        mt[i][j] == 4 or mt[i][j] == 5)):
        return True
    else:
        return False
 
def s4(i, j): # conversion to final direction
 
    if (i >= 0 and i < row_size and j >= 0 and j < col_size and
       vi[i][j] == 0 and (mt[i][j] == 1 or mt[i][j] == 2 or
       mt[i][j] == 6 or mt[i][j] == 5)):
        return True
    else:
        return False
 
 
# search for connection
# We start by pushing the start node (X, Y) into a queue
# with depth 1  and then start processing the queue till
# it is empty.
def bfs(x, y, d):
    push(x, y, d)
    while (r > f) :
        temp = pop()
        i = temp.x
        j = temp.y
        c = temp.d
        depth[i][j] = c
 
        if (mt[i][j] == 1 or mt[i][j] == 3 or
            mt[i][j] == 4 or mt[i][j] == 5) :
            if (s1(i, j + 1)):
                push(i, j + 1, c + 1)
         
        if (mt[i][j] == 1 or mt[i][j] == 2 or
            mt[i][j] == 6 or mt[i][j] == 5) :
            if (s2(i + 1, j)):
                push(i + 1, j, c + 1)
         
        if (mt[i][j] == 1 or mt[i][j] == 3 or
            mt[i][j] == 7 or mt[i][j] == 6) :
            if (s3(i, j - 1)):
                push(i, j - 1, c + 1)
         
        if (mt[i][j] == 1 or mt[i][j] == 2 or
            mt[i][j] == 4 or mt[i][j] == 7) :
            if (s4(i - 1, j)):
                push(i - 1, j, c + 1)
         
     
 
if __name__=='__main__': # main function
 
 
    f = 0
    r = 0
    # matrix
    for i in range(row_size) :
        for j in range(col_size) :
 
            # visited matrix for BFS set to
            # unvisited for every cell
            vi[i][j] = 0
 
            # depth set to max initial value
            depth[i][j] = Max
         
     
 
    if (mt[x][y] != 0): # condition for BFS
        bfs(x, y, 1)
 
    nc = 0
    for i in range(row_size) :
        for j in range(col_size) :
            if (depth[i][j] <= l) :
                print("({}, {})".format(i,j),end='')
                nc+=1
             
         
     
    print(" ",nc)


Output

(1, 0)(1, 1)(1, 2) 3

Complexity Analysis:

  • Time Complexity: O(N * M) where N is the total number of rows and M is the total number of columns
  • Auxiliary Space: O(N * M) 


Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads