Calculate minimum distance in a straight line using BFS - algorithm

Trying to solve this problem using BFS.
Problem Gist: Initial and final position is given for a rook placed in a matrix. You are required to find out minimum number of steps for rook to reach final position. Some position marked with "X" shouldn't be crossed, whereas "." are the allowable positions.
Matrix:
.X.
.X.
...
source position: 0,0
target position: 0,2
answer:3 (0,0) -> (2,0) - > (2,2) -> (0,2)
My solution basically does below:
I start doing BFS from source node and after I dequeue the node I am adding all the vertical and horizontal nodes in memory with the current distance of that node plus 1. After that I am checking if the destination node is present in memory and if it is present I am returning that distance.
This below solution is not working in some of the cases. Any suggestions?
def update_distance(memoize_dist, current, n, count, matrix):
directions = [1, -1, 1, -1]
current_x, current_y = current
temp_x, temp_y = current
for direction in directions:
while temp_x < n and temp_x >= 0:
temp_x += direction
temp = (temp_x, current_y)
if temp_x >= n or temp_x < 0 or matrix[temp_x][current_y] == 'X':
temp_x, temp_y = (current_x, current_y)
break
if temp not in memoize_dist.keys():
memoize_dist[temp] = count
for direction in directions:
while temp_y < n and temp_y >= 0:
temp_y += direction
temp = (current_x, temp_y)
if temp_y >= n or temp_y < 0 or matrix[current_x][temp_y] == 'X':
temp_x, temp_y = (current_x, current_y)
break
if temp not in memoize_dist.keys():
memoize_dist[temp] = count
def get_shortest(n, src, target, matrix):
queue, memoize, memoize_dist = [], {}, {}
queue.append((src[0], src[1], 0))
memoize_dist[(src[0], src[1])] = 0
while len(queue):
x, y, count = queue.pop(0)
cur = (x, y)
if cur in memoize.keys() and memoize[cur] != -1:
continue
memoize[cur] = 1
update_distance(memoize_dist, cur, n, count+1, matrix)
if target in memoize_dist.keys():
return memoize_dist[target]
directions = [1, -1, 1, -1]
for direction in directions:
if cur[0]+direction < n and cur[0]+direction >= 0 and matrix[cur[0]+direction][cur[1]] != 'X':
queue.append((cur[0]+direction, cur[1], memoize_dist[(cur[0]+direction, cur[1])]))
if cur[1]+direction < n and cur[1]+direction >= 0 and matrix[cur[0]][cur[1]+direction] != 'X':
queue.append((cur[0], cur[1]+direction, memoize_dist[(cur[0], cur[1]+direction)]))
n = int(input())
matrix = []
for i in range(n):
matrix.append(input())
start_x, start_y, dest_x, dest_y = map(int, input().split(" "))
print(get_shortest(n, (start_x, start_y), (dest_x, dest_y), matrix))

Related

How can I solve this problem using dynamic programming?

Given a list of numbers, say [4 5 2 3], I need to maximize the sum obtained according to the following set of rules:
I need to select a number from the list and that number will be removed.
Eg. selecting 2 will have the list as [4 5 3].
If the number to be removed has two neighbours then I should get the result of this selection as the product of the currently selected number with one of its neighbours and this product summed up with the other neighbour. eg.: if I select 2 then I can have the result of this selction as 2 * 5 + 3.
If I select a number with only one neighbour then the result is the product of the selected number with its neighbour.
When their is only one number left then it is just added to the result till now.
Following these rules, I need to select the numbers in such an order that the result is maximized.
For the above list, if the order of selction is 4->2->3->5 then the sum obtained is 53 which is the maximum.
I am including a program which lets you pass as input the set of elements and gives all possible sums and also indicates the max sum.
Here's a link.
import itertools
l = [int(i) for i in input().split()]
p = itertools.permutations(l)
c, cs = 1, -1
mm = -1
for i in p:
var, s = l[:], 0
print(c, ':', i)
c += 1
for j in i:
print(' removing: ', j)
pos = var.index(j)
if pos == 0 or pos == len(var) - 1:
if pos == 0 and len(var) != 1:
s += var[pos] * var[pos + 1]
var.remove(j)
elif pos == 0 and len(var) == 1:
s += var[pos]
var.remove(j)
if pos == len(var) - 1 and pos != 0:
s += var[pos] * var[pos - 1]
var.remove(j)
else:
mx = max(var[pos - 1], var[pos + 1])
mn = min(var[pos - 1], var[pos + 1])
s += var[pos] * mx + mn
var.remove(j)
if s > mm:
mm = s
cs = c - 1
print(' modified list: ', var, '\n sum:', s)
print('MAX SUM was', mm, ' at', cs)
Consider 4 variants of the problem: those where every element gets consumed, and those where either the left, the right, or both the right and left elements are not consumed.
In each case, you can consider the last element to be removed, and this breaks the problem down into 1 or 2 subproblems.
This solves the problem in O(n^3) time. Here's a python program that solves the problem. The 4 variants of solve_ correspond to none, one or the other, or both of the endpoints being fixed. No doubt this program can be reduced (there's a lot of duplication).
def solve_00(seq, n, m, cache):
key = ('00', n, m)
if key in cache:
return cache[key]
assert m >= n
if n == m:
return seq[n]
best = -1e9
for i in range(n, m+1):
left = solve_01(seq, n, i, cache) if i > n else 0
right = solve_10(seq, i, m, cache) if i < m else 0
best = max(best, left + right + seq[i])
cache[key] = best
return best
def solve_01(seq, n, m, cache):
key = ('01', n, m)
if key in cache:
return cache[key]
assert m >= n + 1
if m == n + 1:
return seq[n] * seq[m]
best = -1e9
for i in range(n, m):
left = solve_01(seq, n, i, cache) if i > n else 0
right = solve_11(seq, i, m, cache) if i < m - 1 else 0
best = max(best, left + right + seq[i] * seq[m])
cache[key] = best
return best
def solve_10(seq, n, m, cache):
key = ('10', n, m)
if key in cache:
return cache[key]
assert m >= n + 1
if m == n + 1:
return seq[n] * seq[m]
best = -1e9
for i in range(n+1, m+1):
left = solve_11(seq, n, i, cache) if i > n + 1 else 0
right = solve_10(seq, i, m, cache) if i < m else 0
best = max(best, left + right + seq[n] * seq[i])
cache[key] = best
return best
def solve_11(seq, n, m, cache):
key = ('11', n, m)
if key in cache:
return cache[key]
assert m >= n + 2
if m == n + 2:
return max(seq[n] * seq[n+1] + seq[n+2], seq[n] + seq[n+1] * seq[n+2])
best = -1e9
for i in range(n + 1, m):
left = solve_11(seq, n, i, cache) if i > n + 1 else 0
right = solve_11(seq, i, m, cache) if i < m - 1 else 0
best = max(best, left + right + seq[i] * seq[n] + seq[m], left + right + seq[i] * seq[m] + seq[n])
cache[key] = best
return best
for c in [[1, 1, 1], [4, 2, 3, 5], [1, 2], [1, 2, 3], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]:
print(c, solve_00(c, 0, len(c)-1, dict()))

Scala - Shortest Path Between Two Nodes Recursive Algorithm

I am implementing Dijkstra's shortest path algorithm recursivingly in Scala, but I am having some trouble. I am getting the incorrect output for nodes 3 to 2, called like this, shortestPath(3, 2, x, BitSet.empty). This outputs 6, but the correct answer should be 7. I cannot seem to figure out what's wrong with my code.
var x = ListBuffer(ListBuffer(0, 2, 3, 4),
ListBuffer(2, 0, 0, 0),
ListBuffer(3, 0, 0, 0),
ListBuffer(4, 0, 0, 0))
My code is here shown below.
def shortestPath(cur: Int, dest: Int, graph: ListBuffer[ListBuffer[Int]], visited: BitSet) :Int = {
val newVisited = visited + cur
if(cur == dest) 0
else {
var pathLength = for(i <- graph(cur).indices; if(!visited(i) && graph(cur)(i) > 0)) yield {
graph(cur)(i) + shortestPath(i, dest, graph, newVisited)
}
if (pathLength.isEmpty) 0 else pathLength.min
}
}
As pointed out by obourgain, the critical error of the code is at interpreting the min-distance as 0 when two nodes are not connected.
The min-distance between two nodes should be infinity if they are disconnected, this is because the cost of two disconnected nodes must be greater than the cost of any connected nodes, and one simple fix to your code is to identify infinity with Int.MaxValue.
def shortestPath(cur: Int, dest: Int, graph: ListBuffer[ListBuffer[Int]], visited: BitSet) :Int = {
val newVisited = visited + cur
if(cur == dest) 0
else {
var pathLength = for(i <- graph(cur).indices; if(!visited(i) && graph(cur)(i) > 0)) yield {
val sLen = shortestPath(i, dest, graph, newVisited)
if (graph(cur)(i) > Int.MaxValue - sLen) Int.MaxValue else graph(cur)(i) + sLen // change #1
}
if (pathLength.isEmpty) Int.MaxValue else pathLength.min // change #2
}
}
This modification will give the expected answer Int = 7 when invoking shortestPath(3, 2, x, new BitSet()).
The code commented with "change #1" is to prevent integer overflow when the destination node is not reachable by the neighbor node (thus the min-distance is Int.MaxValue), and the code commented with "change #2" is to treat the min-distance between two nodes as "infinite" when they are disconnected.
The error is on the last line:
if (pathLength.isEmpty) 0 else pathLength.min
If pathLength.isEmpty, it means the two points are not connected. However, the function returns 0, which is interpreted as a connection with weight 0.

Maximum sum of path from left column to right column

I'm trying to calculate the maximum sum that can be achieved in going from left column to right column in a grid. Allowed movements are up, down, right. I've implemented this solution (it's Breadth First Search) :
for(int i=1; i<=n; i++) {
Queue<Position> q = new LinkedList<Position>();
q.add(new Position(i, 1));
dp[i][1] = map[i][1];
while(!q.isEmpty()) {
Position node = q.poll();
visited[node.n][node.m] = 1;
if(dp[node.n][node.m] > max) {
max = dp[node.n][node.m];
}
if(visited[node.n-1][node.m] != 1 && node.n != 1 && dp[node.n-1][node.m] < dp[node.n][node.m] + map[node.n-1][node.m] && map[node.n-1][node.m] != -1) {
dp[node.n-1][node.m] = dp[node.n][node.m] + map[node.n-1][node.m];
q.add(new Position(node.n-1, node.m));
}
if(visited[node.n+1][node.m] != 1 && node.n != n && dp[node.n +1][node.m] < dp[node.n][node.m] + map[node.n+1][node.m] && map[node.n+1][node.m] != -1) {
dp[node.n +1][node.m] = dp[node.n][node.m] + map[node.n+1][node.m];
q.add(new Position(node.n + 1, node.m));
}
if(visited[node.n][node.m+1] != 1 && node.m != m && dp[node.n][node.m+1] < dp[node.n][node.m] + map[node.n][node.m+1] && map[node.n][node.m+1] != -1) {
dp[node.n][node.m+1] = dp[node.n][node.m] + map[node.n][node.m+1];
q.add(new Position(node.n, node.m+1));
}
}
}
static class Position {
int n, m;
public Position(int row, int column) {
this.n = row;
this.m = column;
}
}
Example Input:
-1 4 5 1
2 -1 2 4
3 3 -1 3
4 2 1 2
The problem with my solution is it should reach 2 (in last row 2nd column) by following 4->3->3->2 but my solution put 2 in visited state so it won't check it. And if I remove visited array, it will get trapped in infinite loop of up, down, up, down on any cell.
Edit : Each point can be visited only once.
This problem can be solved with a linear programming approach, but there is a small twist because you cannot visit each cell more than once but the movements can actually take you to that condition.
To solve the issue you can however note that in a given position (x, y) you either
just arrived at (x, y) from (x-1, y) and therefore you are allowed to go up, down or right (unless you're on the edges, of course)
arrived at (x, y) from (x, y-1) (i.e. from above) and then you're allowed only to go down or right
arrived at (x, y) from (x, y+1) (i.e. from below) and then you're allowed only to go up or right
This translates directly in the following recursive-memoized solution (code is in Python):
matrix = [[-1, 4, 5, 1],
[ 2,-1, 2, 4],
[ 3, 3,-1, 3],
[ 4, 2, 1, 2]]
rows = len(matrix)
cols = len(matrix[0])
cache = {}
def maxsum(dir, x, y):
key = (dir, x, y)
if key in cache: return cache[key]
base = matrix[y][x]
if x < cols-1:
best = base + maxsum("left", x+1, y)
else:
best = base
if dir != "above" and y > 0:
best = max(best, base + maxsum("below", x, y-1))
if dir != "below" and y < rows-1:
best = max(best, base + maxsum("above", x, y+1))
cache[key] = best
return best
print(max(maxsum("left", 0, y) for y in range(rows)))
If you are not allowed to step over a negative value (even if that would guarantee a bigger sum) the changes are trivial (and you need to specify what to return if there are no paths going from left column to right column).

Find close path or region using recursive method

I have a object in 2d array and i want to traverse through them top, left, right for that object acutally i want to check if there are making some loop or better making some closed region. See this picture for better explanation.
Acutally i have a X x Y of slot and when user touch on any of the region it adds the brick there so what i want to do is every time user add a brick check if it is making a close path.
I have writen recursive function for that but it's not working fine it always go for the top only and not right and left. Here is the code
function checkTrap(y,x)
if all_tiles[y][x].state == "changed" then --if brick is added at that location
last_move_y = y
last_move_x = x
--check for top
y = y - 1
if( y >= 1 and y <= 6 and (last_move_y ~= y or last_move_x ~= x) ) then
print("Moved to top at"..y..", "..x)
return checkTrap(y, x)
end
--check for bottom
y = y + 1
if( y >= 1 and y <= 6 and (last_move_y ~= y or last_move_x ~= x) ) then
print("Moved to bottom at"..y..", "..x)
return checkTrap(y, x)
end
--check for left
x = x - 1
if( x >= 1 and x <= 6 and (last_move_y ~= y or last_move_x ~= x) ) then
print("Moved to left at"..y..", "..x)
return checkTrap(y, x)
end
--check for right
x = x + 1
if( x >= 1 and x <= 6 and (last_move_y ~= y or last_move_x ~= x) ) then
print("Moved to right at"..y..", "..x)
return checkTrap(y, x)
end
elseif all_tiles[y][x] == object then
print("it's a loop"..y..", "..x)
return true;
else
print("not changed")
return false
end
end
Edit : New Solution
function findClosedRegion()
local currFlag, isClose = -1, false
local isVisited = {
{-1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1}}
local k, m = 1, 1
while k <= 6 and not isClose
do
print("K "..k)
while m <= 6 and not isClose
do
print("M "..m)
if not isBrick[k][m] and isVisited[k][m] == -1 then
local cellsi = Stack:Create()
local cellsj = Stack:Create()
cellsi:push(k)
print("Pushed k "..k)
cellsj:push(m)
print("Pushed m "..m)
currFlag = currFlag + 1
isClose = true
while cellsi:getn() > 0 and isClose do
local p = cellsi:pop()
print("Pop p "..p)
local q = cellsj:pop()
print("Pop q "..q)
if( p >= 1 and p <= 6 and q >= 1 and q <= 6 ) then
if(not isBrick[p][q]) then
print("white ")
if(isVisited[p][q] == -1) then
print("invisited")
isVisited[p][q] = currFlag
cellsi.push(p - 1)
cellsj.push(q)
cellsi.push(p + 1)
cellsj.push(q)
cellsi.push(p)
cellsj.push(q + 1)
cellsi.push(p)
cellsj.push(q - 1)
cellsi:list()
else
if(isVisited[p][q] < currFlag) then
print("visited < currFlag")
isClose = false
end
end
end
else
isClose = false
end --p and q if ends here
end -- tile while end
else
--print("changed and not -1")
end
m = m + 1
end -- m while end
if(isClose) then
print("Closed path")
end
m = 1
k = k + 1
end -- k while end
end
The structure of the implementation does not recurse into other directions as only the first branch is called; somehow all neighbors should be included. Apparently you try to implement a kind of Deph-first search on your array. The approach seems absolutely rightm, but all neighbors of a cell have to be taken into account. What perhaps would help most would be to do a connected component analysis and fill all the connected components which touch the border.
EDITED:
Instead if searching with the help of black cells, we should search with white cells because your goal is to find area bound by black cells, even if diagonally adjacent. We should find a group of white cells which is only bordered by black cells and not by the border of the whole main grid. That should satisfy your purpose.
JS Fiddle: http://jsfiddle.net/4d4wqer2/
This is the revised algorithm I came up with:
for each cell and until closed area not found
if white and visitedValue = -1
push cell to stack
while stack has values and closed area not found
pop cell from stack
if invalid cell // Cell coordinates are invalid
this area is not closed, so break from the while
else
if white
if visitedValue = -1
{
mark visited
push neighboring four cells to the stack
}
else
if visitedValue > currVisitNumber // The current cells are part of previous searched cell group, which was not a closed group.
this area is not closed, so break from the while
if closed area found
show message
Programmed using JQuery:
function findArea() {
var currFlag = -1, isvisited = [], isClosed = false;
for (var k = 0; k < rows; k++) { // Initialize the isvisited array
isvisited[k] = [];
for (var m = 0; m < cols; m++)
isvisited[k][m] = -1;
}
for (var k = 0; k < rows && !isClosed; k++)
for (var m = 0; m < cols && !isClosed; m++) {
if (!isblack[k][m] && isvisited[k][m] == -1) { // Unvisited white cell
var cellsi = [k], cellsj = [m];
currFlag++;
isClosed = true;
while (cellsi.length > 0 && isClosed) { // Stack has cells and no closed area is found
var p = cellsi.pop(), q = cellsj.pop();
if (p >= 0 && p < rows && q >= 0 && q < cols) { // The cell coord.s are valid
if (!isblack[p][q])
if (isvisited[p][q] == -1) {
isvisited[p][q] = currFlag; // Mark visited
cellsi.push(p - 1); // Push the coord.s of the four adjacent cells
cellsj.push(q);
cellsi.push(p + 1);
cellsj.push(q);
cellsi.push(p);
cellsj.push(q + 1);
cellsi.push(p);
cellsj.push(q - 1);
}
else
if (isvisited[p][q] < currFlag) // The current group of white cells was part of a previous group of white cells which were found to be unbound by the black cells. So, skip this group.
isClosed = false;
}
else
isClosed = false; // The current cell is out of border. Hence skip the whole group.
}
}
}
if (isClosed)
alert('Closed area found');
}
JS Fiddle: http://jsfiddle.net/4d4wqer2/

Algorithm to find the total number of connected sets in a matrix

i wanted to know which algorithm should i apply here. Would a DFS do?
Given a 2–d matrix. Find the total number of connected sets in that matrix.
Connected set can be defined as group of cell(s) which has 1 mentioned on it and have at least one other cell in that set with which they share the neighbor relationship. A cell with 1 in it and no surrounding neighbor having 1 in it can be considered as a set with one cell in it. Neighbors can be defined as all the cells adjacent to the given cell in 8 possible directions (i.e. N, W, E, S, NE, NW, SE, SW direction). A cell is not a neighbor of itself.
For example:
1 0 0 1
0 0 1 0
0 0 1 0
1 0 0 1
number of connected sets is 3
0 0 1 0 0 1 0 0
1 0 0 0 0 0 0 1
0 0 1 0 0 1 0 1
0 1 0 0 0 1 0 0
1 0 0 0 0 0 0 0
0 0 1 1 0 1 1 0
1 0 1 1 0 1 1 0
0 0 0 0 0 0 0 0
number of connected set is 9.
I don't think you will need to think of it as a general graph problem and apply any algorithm such as BFS or DFS.
You will need to do three scans of the matrix.
scan 1:
start from the top
give every number each 1 with 1..n, in you example the first row would after that step would look like
1 0 0 2
go to the next line and for every 1 in the row check if the neighbor to your left is non-0
if non-0 take on the value to the left
if 0 check for non-0 neighbors in the previous line and take on the value of the left most one
if all of those are 0 that simply add 1 to the maximum number given so far
repeat 2 until last line has been processed
and your example should look like follows
1 0 0 2
0 0 2 0
0 0 2 0
3 0 0 2
scan 2:
start from the bottom
check if each neighbor has the same number as the left most neighbor as well as the same number as the neighbor in the row below it
basically if you have a matrix like this
1 0 2
1 0 2
0 1 0
to check ensure that a set has really the same number
scan 3:
count the number of unique non-0 entries in the matrix
Connected-component labeling algorithm is intended to mark out connected groups of elements (both for 4-connectivity and for 8-connectivity)
Pythonic Implementation, More understandable code:
# sea is 2 D array of 0 and 1s we have to find 1's group surrounded by 0's
def dfs(sea, i, j, b, h, visited):
surround = ((-1, -1), (0, -1), (1, -1),
(-1, 0), (1, 0),
(-1, 1), (0, 1), (1, 1)
)
if can_visit(sea, i, j, b, h, visited):
for s in surround:
visited[(i, j)] = 1
dfs(sea, i + s[0], j + s[1], b, h, visited)
def can_visit(sea, i, j, b, h, visited):
if i >= 0 and j >= 0 and i < b and j < h:
if (i, j) not in visited and sea[i][j] == 1:
return True
def find_island(sea):
visited = {}
h = len(sea)
count = 0
for i, row in enumerate(sea):
b = len(row)
for j, item in enumerate(row):
if can_visit(sea, i, j, b, h, visited):
count += 1
dfs(sea, i, j, b, h, visited)
return count
sea = [[1, 1, 0, 0, 0],
[0, 1, 0, 0, 1],
[1, 0, 0, 1, 1],
[0, 0, 0, 0, 0],
[1, 0, 1, 0, 1]
]
print find_island(sea)
You want to use a disjoint set datastructure and algorithm. This will pick a unique representative for each connected component, which you can count at the end.
To efficiently evaluate which elements are neighbors, you can scan the matrix line by line, maintaining a list of segments (of consecutive 1's) from the previous line, while determining which segments on the current line are adjacent to them.
There are 3 connected sets. All 1 which are neighbors of each other are considered as one single set. All 1 at a[1,4], a[2,3], a[3,3] and a[4,4] form one set and one at a[1,1] form one set and one at a[4,1] forms one set.
Scan the matrix for 1s. When you find one, call a recursive function that marks off its connected component if it is not already identified as being in one. Use recursion to find connected components. Have a quick lookup somewhere that tells you whether a given node has already been identified as being in a connected component to avoid identifying connected components 2x, and to avoid infinite loops while traversing a connected component.
If you want do it just by your matrix (without extra memory), do it as follow:
Set scanner position as [0,0]
Set a counter to zero.
Scan matrix from current scanner position row by row (and cell by cell) and find one 1 and set scanner position to next element after this 1, if there isn't any 1 go to step 6.
Set related one to counter+2 and recursively find all of its 1 neighbors and also set them to count + 2.
count = count + 1
Go to step 2.
output count.
PS: It's clear if the scanner position is greater than matrix size your algorithm will finishes (I didn't wrote this to prevent confusion).
This isn't nearly as hard as it looks. In fact, this feels very strongly like something a professor would assign for an assignment in first year Computer Science. So if this is homework, you should tag it as such.
However, the solution is fairly easy.
for (int y = 0; y < arr.height(); y++)
{
for (int x = 0; x < arr.width(); x++)
{
if (arr[x][y] == 1)
{
if (CheckIfConnected(x, y, arr))
{
connectedPositionsX.Add(x);
connectedPositionsY.Add(y);
}
}
}
}
Where connectedPositions would be a linked list or whatever you want to store sets with.
arr is a 2D array containing a matrix of the type you specified above.
CheckIfConnected can be implemented fairly simply as well.
bool CheckIfConnected(int x, int y, int[][]arr)
{
if (arr.width() >= 2) || (arr.height() >= 2)
{
if ((x < arr.width()) && (x >= 0) && (y < arr.height()) && (y >= 0))
{
if ((x-1) >= 0) //West
{
if (arr[x-1][y] == 1)
{
adjCount[x-1][y] += 1;
return true;
}
}
if (((x-1) >= 0) && ((y-1) >= 0)) //Northwest
{
if (arr[x-1][y-1] == 1)
{
adjCount[x-1][y-1] += 1;
return true;
}
}
if ((y-1) >= 0) //North
{
if (arr[x][y-1] == 1)
{
adjCount[x][y-1] += 1;
return true;
}
}
if (((x+1) < arr.width()) && ((y-1) >= 0)) //Northeast
{
if (arr[x+1][y-1] == 1)
{
adjCount[x+1][y-1] += 1;
return true;
}
}
if ((x+1) < arr.width()) //East
{
if (arr[x+1][y] == 1)
{
adjCount[x+1][y] += 1;
return true;
}
}
//I'll let you implement Southeast to Southwest on your own,
//the pattern is clear now.
}
}
return false;
}
From there, you know how many times you found a pairing on each position in the grid. This helps you keep track of your connections.
The counts in the 2D array adjCount keeps track of this for you.
You could also go through and modify Dijkstra's Algorithm to do it recursively for you. Since you mentioned DFS (Depth First Search) I'm assuming your professor or teacher wants you to go about solving it that way.
In that case:
Here is Dijkstra's Algorithm in Pseudo Code:
http://en.wikipedia.org/wiki/Dijkstra's_algorithm
Hope that helps! Cheers!
Just keep searching in East, SouthEast, South and SouthWest direction at one go recursively for each node having value as 1.
If the call to visit function is a fresh call and not from recursion increase the connected components.
import java.util.Scanner;
public class Solution {
public static void visit(int[][] ar, boolean[][] v,int i, int j){
int size = ar.length;
if(ar[i][j] == 1){
v[i][j] = true;
if(j>0 && i<size-1){
visit(ar,v,i+1,j-1); // SouthWest
}
if(i<size-1){
visit(ar,v,i+1,j); // South
if(j < size-1)
visit(ar,v,i+1,j+1); // SouthEast
}
if(j<size-1)
visit(ar,v,i,j+1); // East
}
}
public static void main(String[] args) {
int[][] ar;
int count = 0;
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
ar = new int[n][n];
boolean[][] v = new boolean[n][n];
for(int i=0; i<n ; i++) {
for(int j=0; j<n; j++){
ar[i][j] = sc.nextInt();
v[i][j] = false;
}
}
for(int i=0; i<n ; i++) {
for(int j=0; j<n; j++){
if(ar[i][j] == 1 && !v[i][j]){
count++;
visit(ar,v,i,j);
}
}
}
System.out.println(count);
}
}
I have a class to help you find the total number of connected components in your 2D array. My class not only gives you the total number, but also gives you the clusters and visualize them for you. You can comment out the parts that you don't need. Please see this class in (java): https://github.com/m-vahidalizadeh/foundations/blob/master/src/algorithms/ConnectedComponetns.java
If you use python, there is a function in scipy to find this number.
from scipy.ndimage import label
data = [[0, 0, 1, 0, 0, 1, 0, 0],
[1, 0, 0, 0, 0, 0, 0, 1],
[0, 0, 1, 0, 0, 1, 0, 1],
[0, 1, 0, 0, 0, 1, 0, 0],
[1, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 0, 1, 1, 0],
[1, 0, 1, 1, 0, 1, 1, 0],
[0, 0, 0, 0, 0, 0, 0, 0]]
connection_structure = [[1,1,1],
[1,0,1],
[1,1,1]]
_, N = label(data, connection_structure)
print(N)
>>> 9

Resources