What should be the recurrence relation? - algorithm

I am trying to solve this problem using dynamic programming but getting wrong answer. I think the recurrence i am using is incorrect. What should be the recurrence relation for the problem and what information should the dp state hold? At present, i am using a 2-dimensional array where dp[i][j] denotes the maximum number of scoops for rectangle of size (i x j), So answer will be dp[n - 1][n - 1].-> Problem Statement
My Code:
1) s[n][n] is the grid that is given in the problem.
2) end[i][j].first is 1 if s[i][j] is used in the solution for (i x j) rectangle and 0 otherwise.
3) end[i][j].second is 1 if s[i][j] is joined with upper-# and 2 if left-# and 0 if s[i][j] is not used.
int dp[n][n];
pair<int, int> end[n][n];
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
// w is the answer for (i x j) without using s[i][j]
w = (i - 1 >= 0 ? dp[i - 1][j] : 0) + (j - 1 >= 0 ? dp[i][j - 1] : 0) - (i - 1 >= 0 && j - 1 >= 0 ? dp[i - 1][j - 1] : 0);
if (i - 1 >= 0 && j - 1 >= 0 && end[i - 1][j].first == 1 && end[i - 1][j].second == 2 && end[i][j - 1].first == 1 && end[i][j - 1].second == 1) w--;
x = y = 0;
if (s[i][j] == '#') {
if (i > 0) {
// using the upper # if present
if (s[i - 1][j] == '#') x = 1 + (i - 2 >= 0 ? dp[i - 2][j] : 0) + (j - 1 >= 0 ? dp[i][j - 1] : 0) - (i - 2 >= 0 && j - 1 >= 0 ? dp[i - 2][j - 1] : 0);
if (i - 2 >= 0 && j - 1 >= 0 && end[i - 1][j - 1].first == 1 && end[i - 1][j - 1].second == 1 && end[i - 2][j].first == 1 && end[i - 2][j].second == 2) x--;
if (x <= w) x = 0;
}
if (j > 0) {
//using the left # if present
if (s[i][j - 1] == '#') y = 1 + (i - 1 >= 0 ? dp[i - 1][j] : 0) + (j - 2 >= 0 ? dp[i][j - 2] : 0) - (i - 1 >= 0 && j - 2 >= 0 ? dp[i - 1][j - 2] : 0);
if (i - 1 >= 0 && j - 2 >= 0 && end[i - 1][j - 1].first == 1 && end[i - 1][j - 1].second == 2 && end[i][j - 2].first == 1 && end[i][j - 2].second == 1) y--;
if (y <= w) y = 0;
}
}
// choosing the maximum of the three and accordingly assigning end[i][j]
if (w >= x && w >= y) {
dp[i][j] = w;
end[i][j] = make_pair(0, 0);
} else if (x > w && x > y) {
dp[i][j] = x;
end[i][j] = make_pair(1, 1);
} else {
dp[i][j] = y;
end[i][j] = make_pair(1, 2);
}
}
}

This problem is not about dynamic programming. It's about the maximum matching. Let's paint the grid with black and white colors(like a chess board). Now we have a bipartite graph(black cells are in the first part and white cells are in the second one). We should add edges between adjacent cells if both of them contain oil. The answer is the size of the maximum matching in this graph.

Related

Explanation for Booth's Algorithm for Lexicographically minimal string rotation

Can someone please explain or comment me this code for Booth's Algorithm for Lexicographically minimal string rotation from wikipedia (https://en.wikipedia.org/wiki/Lexicographically_minimal_string_rotation#Booth.27s_Algorithm)?
def least_rotation(S: str) -> int:
"""Booth's algorithm."""
S += S # Concatenate string to it self to avoid modular arithmetic
f = [-1] * len(S) # Failure function
k = 0 # Least rotation of string found so far
for j in range(1, len(S)):
sj = S[j]
i = f[j - k - 1]
while i != -1 and sj != S[k + i + 1]:
if sj < S[k + i + 1]:
k = j - i - 1
i = f[i]
if sj != S[k + i + 1]: # if sj != S[k+i+1], then i == -1
if sj < S[k]: # k+i+1 = k
k = j
f[j - k] = -1
else:
f[j - k] = i + 1
return k
I am lost with the indices and the k etc. What does it mean, why is there [j - k - 1] indexing etc.?
Thanks!

How to approach this two dimensional array problem?

Problem (THE QUESTION)
Strokes to paint
Alex wants to paint a picture. In one stroke, Alex can only paint the same colored cells which are joined via some edge.
Given the painting as a 2-dimensional array of letters indicating colors, determine the minimum number of strokes to completely paint the picture.
Example: The canvas height, h = 3 and width, w = 5 is to be painted with picture=["aabba", "aabba", "aaacb"]. The diagram below shows the 5 strokes needed to paint the canvas. It takes two strokes each for colors a and b, and one for c
a a b b a
a a b b a
a a a c b
Function Description Complete the function strokesRequired in the editor below. The function must return an integer, the minimum number of strokes required to paint the canvas.
strokesRequired has the following parameter(s): picture[picture[0],...picture[h-1]] an array of strings where each string represents one row of the picture to be painted
Constraints
1 <= h <= 10^5
1<= w <= 10^5
1 <= h*w <= 10^5
len(pictureffl) = w (where 0 <= i < h)
picture[i][j] <- (a, b, c) (where 0 <= i < h and 0 <= j < w)
Hello.. so i attended one company interview and they asked me this problem and iam not getting any ideas please help
class Paint:
def __init__(self, row, col, arr):
self.ROW = row
self.COL = col
self.arr = arr
def visit(self, i, j, visited):
ele = self.arr[i][j]
for k in range(i,self.ROW):
for l in range(j, self.COL):
if self.arr[k][l]==ele:
visited[k][l]=True
v=l
if l>0 and self.arr[k][l-1]==ele and not visited[k][l-1]:
self.visit(k, l-1, visited)
if k>0 and self.arr[k-1][l]==ele and not visited[k-1][l]:
self.visit(k-1, l, visited)
elif l>=v:
break
# 2D matrix
def count_cells(self):
# Make an array to mark visited cells.
# Initially all cells are unvisited
visited = [[False for j in range(self.COL)]for i in range(self.ROW)]
# Initialize count as 0 and travese
count = 0
for i in range(self.ROW):
for j in range(self.COL):
# If a cell value false then not visited yet
# then visit
if visited[i][j] == False:
# Visit all cells in the array
self.visit(i, j, visited)
print(visited)
count += 1
return count
arr = ["aabba", "aabba", "aaacb"]
row = len(arr)
col = len(arr[0])
p = Paint(row, col, arr)
print (p.count_cells())
function visit(picture, i, j, visitedBoxes) {
const currentElem = picture[i][j];
if (picture[i][j] === currentElem) {
visitedBoxes[i][j] = true;
// go in four directions
// south
if (i + 1 < picture.length && picture[i+1][j] === currentElem && visitedBoxes[i+1][j] === false) {
visit(picture, i+1, j, visitedBoxes);
}
// west
if (j+ 1 < picture[i].length && picture[i][j+1] === currentElem && visitedBoxes[i][j+1] === false) {
visit(picture, i, j+1, visitedBoxes);
}
// north
if (i > 0 && picture[i-1][j] === currentElem && visitedBoxes[i-1][j] === false) {
visit(picture, i-1, j, visitedBoxes);
}
// west
if (j > 0 && picture[i, j-1] === currentElem && visitedBoxes[i, j-1] === false) {
visit(picture, i, j-1, visitedBoxes);
}
}
}
function countStrokes(picture) {
const visitedBoxes = [];
for (let i = 0; i < picture.length; i++) {
visitedBoxes[i] = [];
for(let j = 0; j < picture[i].length; j++) {
visitedBoxes[i][j] = false;
}
}
let srokesCount = 0;
for (let i = 0; i < picture.length; i++) {
for (let j = 0; j < picture[i].length; j++) {
if (!visitedBoxes[i][j]) {
visit(picture, i, j, visitedBoxes);
srokesCount++;
}
}
}
console.log('Strokes Count', srokesCount);
}
countStrokes(['aaaba', 'ababa', 'aacba']);
This will output 5.
Also you can use
function printVisited(visitedBoxes) {
for (let i = 0; i < visitedBoxes.length; i++) {
let str = ''
for(let j = 0; j < visitedBoxes[i].length; j++) {
str += visitedBoxes[i][j] ? '1 ': '0 ';
}
console.log(str);
}
console.log('-------------');
}
to print after each loop.
Output
1 1 1 0 0
1 0 1 0 0
1 1 0 0 0
-------------
1 1 1 1 0
1 0 1 1 0
1 1 0 1 0
-------------
1 1 1 1 1
1 0 1 1 1
1 1 0 1 1
-------------
1 1 1 1 1
1 1 1 1 1
1 1 0 1 1
-------------
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
-------------
Strokes Count 5

Confusion Regarding deepest pit within an Array

I got this question as prerequisite for an interview,
A non-empty zero-indexed array A consisting of N integers is given. A
pit in this array is any triplet of integers (P, Q, R) such that: 0 ≤
P < Q < R < N;
sequence [A[P], A[P+1], ..., A[Q]] is strictly decreasing, i.e. A[P] >
A[P+1] > ... > A[Q];
sequence A[Q], A[Q+1], ..., A[R] is strictly increasing, i.e. A[Q] <
A[Q+1] < ... < A[R].
The depth of a pit (P, Q, R) is the number min{A[P] − A[Q], A[R] −
A[Q]}. For example, consider array A consisting of 10 elements such
that:
A[0] = 0
A[1] = 1
A[2] = 3
A[3] = -2
A[4] = 0
A[5] = 1
A[6] = 0
A[7] = -3
A[8] = 2
A[9] = 3
Triplet (2, 3, 4) is one of pits in this array, because sequence
[A[2], A[3]] is strictly decreasing (3 > −2) and sequence [A[3], A[4]]
is strictly increasing (−2 < 0). Its depth is min{A[2] − A[3], A[4] −
A[3]} = 2.
Triplet (2, 3, 5) is another pit with depth 3.
Triplet (5, 7, 8) is yet another pit with depth 4. There is no pit in
this array deeper (i.e. having depth greater) than 4.
It says that Triplet (5, 7, 8) has the deepest pit depth of 4.
but isn't Triplet (2, 7, 9) has the deepest pit depth 6?
corresponding value of Triplet (2, 7, 9) is (3, -3, 3) and it also satisfies the conditions mentioned, i.e.
1) 0 ≤ P < Q < R < N
2) A[P] > A[P+1] > ... > A[Q] and A[Q] < A[Q+1] < ... < A[R]
so in this case min{A[P] − A[Q], A[R] − A[Q]} is 6.
What am i missing here?
P.S. if you think this post does not belong here in this forum then please point out where should i post it.
See the sequence from P to Q for 2 to 7.
It is 3 -2 0 1 0 -3.
sequence [A[P], A[P+1], ..., A[Q]] is strictly decreasing, i.e. A[P] > A[P+1] > ... > A[Q];
The rule says that this should be a decreasing sequence. But it isn't. 3>-2 but -2 is not greater than 0. Here the sequence breaks.
From 7 to 9. No problem as the sequence is increasing. -3<2<3.
answer of the deepest pit problem in swift :
func solution(_ array: [Int]) -> Int {
//guaranty we have at least three elements
if array.isEmpty {
print("isEmpty")
return -1
}
if array.count < 3 {
print("is less than 3")
return -1
}
//extremum point; max or min points
var extremumPoints = [Int]()
//adding first element
extremumPoints.append(array[0])
//calculate extremum points for 1 to one before last element
for i in 1..<(array.count - 1) {
let isRelativeExtremum = ((array[i] - array[i - 1]) * (array[i] - array[i + 1])) > 0
//we call a point semi-extremum if a point is equal to previous element or next element and not equal to previous element or next element
let isSemiExtremum = ((array[i] != array[i - 1]) && (array[i] == array[i + 1])) || ((array[i] != array[i + 1]) && (array[i] == array[i - 1]))
if isRelativeExtremum || isSemiExtremum {
extremumPoints.append(array[i])
}
}
//adding last element
extremumPoints.append(array[array.count - 1])
//we will hold depthes in this array
var depthes = [Int]()
for i in 1..<(extremumPoints.count - 1) {
let isBottomOfaPit = extremumPoints[i] < extremumPoints[i - 1] && extremumPoints[i] < extremumPoints[i + 1]
if isBottomOfaPit {
let d1 = extremumPoints[i - 1] - extremumPoints[i]
let d2 = extremumPoints[i + 1] - extremumPoints[i]
let d = min(d1, d2)
depthes.append(d)
}
}
//deepest pit
let deepestPit = depthes.max()
return deepestPit ?? -1
}
//****************************
let A = [0,1,3,-2,0,1,0,-3,2,3]
let deepestPit = solution(A)
print(deepestPit) // 4
def deepest(A):
def check(p, q, r, A):
if A[p] > A[q] and A[q] < A[r]:
return min(A[p] - A[q], A[r] - A[q])
else:
return -1
max_depth = 0
for i in range(1, len(A) - 2):
if A[i-1] > A[i] < A[i + 1]:
p = i
r = i
while 0 <= p and r <= len(A) - 1:
depth = check(p, i, r, A)
max_depth = max(max_depth, depth)
p -= 1
r += 1
return max_depth

Algorithm - Given a set of pixels with coordinates, how to find all the contiguous lines in an efficient way?

I am working on an extrusion function to create a mesh given a 2D texture and the thickness of it.
Example:
I have achieved finding the outline of the texture by simply looking for the pixels either near the edge or near transparent ones. It works great even for concave (donut-shaped) shapes but now I am left with an array of outline pixels.
Here is the result:
The problem is that the values, by being ordered from top-left to bottom-right, they are not suitable for building an actual 3D outline.
My current idea is the following:
Step 1.
From index [0], look at the right-hand side for the nearest contiguous point different from the starting point.
If found, move it into another array.
If nothing, look at the bottom. Continue until the starting point has been reached.
Step2.
Pick another pixel, if any, from the pixels remained in the array.
Repeat from Step1.
This, in my head, would work but it seems quite inefficient. Researching, I found about the Moore-Neighbor tracing algorithm but I couldn't find anywhere an example where it worked with convex shapes.
Any thoughts?
At the end, I managed to find my own answer, so here I want to share it:
After finding the outline of a given image (using the alpha value of each pixel), the pixels will be ordered in rows, good for drawing them but bad for constructing a mesh.
So, the next step is to find contiguous lines. This is done by checking first if there are any neighbors to the found pixel giving priority to the ones top/left/right/bottom (otherwise it will skip the corners).
Keep going until no pixels are left in the original array.
Here is the actual implementation (for Babylon.js but the idea works with any other engine):
Playground: https://www.babylonjs-playground.com/#9GPMUY#11
var GetTextureOutline = function (data, keepOutline, keepOtherPixels) {
var not_outline = [];
var pixels_list = [];
for (var j = 0; j < data.length; j = j + 4) {
var alpha = data[j + 3];
var current_alpha_index = j + 3;
// Not Invisible
if (alpha != 0) {
var top_alpha = data[current_alpha_index - (canvasWidth * 4)];
var bottom_alpha = data[current_alpha_index + (canvasWidth * 4)];
var left_alpha = data[current_alpha_index - 4];
var right_alpha = data[current_alpha_index + 4];
if ((top_alpha === undefined || top_alpha == 0) ||
(bottom_alpha === undefined || bottom_alpha == 0) ||
(left_alpha === undefined || left_alpha == 0) ||
(right_alpha === undefined || right_alpha == 0)) {
pixels_list.push({
x: (j / 4) % canvasWidth,
y: parseInt((j / 4) / canvasWidth),
color: new BABYLON.Color3(data[j] / 255, data[j + 1] / 255, data[j + 2] / 255),
alpha: data[j + 3] / 255
});
if (!keepOutline) {
data[j] = 255;
data[j + 1] = 0;
data[j + 2] = 255;
}
} else if (!keepOtherPixels) {
not_outline.push(j);
}
}
}
// Remove not-outline pixels
for (var i = 0; i < not_outline.length; i++) {
if (!keepOtherPixels) {
data[not_outline[i]] = 0;
data[not_outline[i] + 1] = 0;
data[not_outline[i] + 2] = 0;
data[not_outline[i] + 3] = 0;
}
}
return pixels_list;
}
var ExtractLinesFromPixelsList = function (pixelsList, sortPixels) {
if (sortPixels) {
// Sort pixelsList
function sortY(a, b) {
if (a.y == b.y) return a.x - b.x;
return a.y - b.y;
}
pixelsList.sort(sortY);
}
var lines = [];
var line = [];
var pixelAdded = true;
var skipDiagonals = true;
line.push(pixelsList[0]);
pixelsList.splice(0, 1);
var countPixels = 0;
while (pixelsList.length != 0) {
if (!pixelAdded && !skipDiagonals) {
lines.push(line);
line = [];
line.push(pixelsList[0]);
pixelsList.splice(0, 1);
} else if (!pixelAdded) {
skipDiagonals = false;
}
pixelAdded = false;
for (var i = 0; i < pixelsList.length; i++) {
if ((skipDiagonals && (
line[line.length - 1].x + 1 == pixelsList[i].x && line[line.length - 1].y == pixelsList[i].y ||
line[line.length - 1].x - 1 == pixelsList[i].x && line[line.length - 1].y == pixelsList[i].y ||
line[line.length - 1].x == pixelsList[i].x && line[line.length - 1].y + 1 == pixelsList[i].y ||
line[line.length - 1].x == pixelsList[i].x && line[line.length - 1].y - 1 == pixelsList[i].y)) || (!skipDiagonals && (
line[line.length - 1].x + 1 == pixelsList[i].x && line[line.length - 1].y + 1 == pixelsList[i].y ||
line[line.length - 1].x + 1 == pixelsList[i].x && line[line.length - 1].y - 1 == pixelsList[i].y ||
line[line.length - 1].x - 1 == pixelsList[i].x && line[line.length - 1].y + 1 == pixelsList[i].y ||
line[line.length - 1].x - 1 == pixelsList[i].x && line[line.length - 1].y - 1 == pixelsList[i].y
))) {
line.push(pixelsList[i]);
pixelsList.splice(i, 1);
i--;
pixelAdded = true;
skipDiagonals = true;
}
}
}
lines.push(line);
return lines;
}
Algorithm Looping over pixels, we only check each pixel once, skipping empty cells, and store it in a list as there won't be duplicates.
isEmpty implementation depends on how transparency works in your case, if a certain color is considered transparent, below is a case where we have an alpha channel.
threshold is the alpha level that represent the least-visibility for a cell to be considered non-empty.
isBorder will check if any of Moore neighbors is empty, in that case it is a border cell, otherwise it's not because it is surrounded by filled cells.
isEmpty(x,y): image[x,y].alpha <= threshold
isBorder(x,y)
: if isEmpty(x , y-1): return true
: if isEmpty(x , y+1): return true
: if isEmpty(x-1, y ): return true
: if isEmpty(x+1, y ): return true
: if isEmpty(x-1, y-1): return true
: if isEmpty(x-1, y+1): return true
: if isEmpty(x+1, y-1): return true
: if isEmpty(x+1, y+1): return true
: otherwise: return false
getBorderCellList()
: l = empty-list
: for x in 0..image.width
: : for y in 0..image.height
: : : if !isEmpty(x,y)
: : : : if isBorder(x,y)
: : : : : l.add(x,y)
: return l
Optimization You could optimize this by having a pre-computed boolean e[image.width][image.height] where e[x,y] = 1 if image[x,y]is not-empty, then use it directly to check, like isBorder(x,y): e[x-1,y] | e[x+1,y] | .. | e[x+1,y+1].
init()
: for x in 0..image.width
: : for y in 0..image.height
: : : e[x,y] = isEmpty(x,y)
isEmpty(x,y): image[x,y].alpha <= threshold
isBorder(x,y): e[x-1,y] | e[x+1,y] | .. | e[x+1,y+1]
getBorderCellList()
: l = empty-list
: for x in 0..image.width
: : for y in 0..image.height
: : : if not e[x,y]
: : : : if isBorder(x,y)
: : : : : l.add(x,y)
: return l

Insertion Sort - troubles reading MIT Intro to Algos

The MIT Intro to Algorithms describes insertion sort as:
I wrote this in Python as:
def sort(A):
for j in range(1, len(A)):
key = A[j];
i = j - 1;
# i > 0 should be i >= 0
while i > 0 and A[i] > key:
A[i + 1] = A[i]
i = i - 1;
A[i + 1] = key
return A
However the line while i > 0 introduces a bug - the first two keys are in the wrong positions. Changing this to while i >= 0 fixes this problem.
Why is this not included in the MIT Intro book? Am I reading it wrong?
The algorithm in the book is assuming indexing from 1 to A.length, inclusive, which is why it starts at an index of 2. Python has array indexing from 0 to len(A) - 1. You corrected for that in your range, but you neglected to correct for it in the loop test. Doing so fixes the problem.
#pjs is exactly right. I'll add that a methodical way to convert an algorithm written for 1-based arrays to 0-based with no off-by-1 errors is to use the algorithm as-is except subtract 1 at each array reference and then use algebra to simplify. Here you'd end up with:
def sort(A):
for j in range(2, len(A) + 1): # +1 is because Python ranges exclude high limit
key = A[j - 1]
i = j - 1
while i > 0 and A[i - 1] > key:
A[i + 1 - 1] = A[i - 1]
i = i - 1
A[i + 1 - 1] = key
return A
Of course it's easy to simplify by removing + 1 - 1, since that's adding zero! The result works fine.
If you want to make the code prettier with the outer range starting at 1 rather than 2, make the substitution jj = j - 1, which (adding 1 to both sides) means j = jj + 1:
def sort(A):
for jj in range(1, len(A)):
key = A[jj + 1 - 1]
i = jj + 1 - 1
while i > 0 and A[i - 1] > key:
A[i] = A[i - 1]
i = i - 1
A[i] = key
return A
Again removing + 1 - 1s, we have
def sort(A):
for jj in range(1, len(A)):
key = A[jj]
i = jj
while i > 0 and A[i - 1] > key:
A[i] = A[i - 1]
i = i - 1
A[i] = key
return A
This looks great, and I'd stop here. But yet another variation is possible with the substitution ii = i - 1 or i = ii + 1.
def sort(A):
for jj in range(1, len(A)):
key = A[jj]
ii + 1 = jj
while ii + 1 > 0 and A[ii + 1 - 1] > key:
A[ii + 1] = A[ii + 1 - 1]
ii + 1 = ii + 1 - 1
A[ii + 1] = key
return A
Hmmm... Those assignments to ii look weird. But we can straighten everything out with algebra yet again.
def sort(A):
for jj in range(1, len(A)):
key = A[jj]
ii = jj - 1 # Subtracted 1 from both sides
while ii >= 0 and A[ii] > key: # x + 1 > 0 iff x >= 0
A[ii + 1] = A[ii]
ii = ii - 1 # Subtracted 1 from both sides and simplified
A[ii + 1] = key
return A
Lo and behold, we have the code you proposed. Works every time.

Resources