I do not understand how the values in the levenshtein matrix is calculated According to this article. I do know how we arrive at the edit distance of 3. Could someone explain in lay man terms how we arrive at each value in each cell?
Hi I just had a look at the link of the Wikipedia article you shared:
The way the matrix is built is described in "Definition".
Now I will just translate that into what it means and what you need to do to built the matrix all by yourself:
Just to be sure that no basic information is missing: i denotes the row number and j denotes the column number.
So lets start with the first definition line of the matrix:
It says that the matrix is max(i, j), if min(i,j) = 0
The condition will be fulfilled only for elements of the 0-th row and the 0-th column. (Then min(0, j) is 0 and min(i, 0) is 0). So for the 0-th row and the 0-th column you enter the value of max(i,j), which corresponds to the row number for the 0-th column and the column number for the 0-th row.
So far so good:
k i t t e n
0 1 2 3 4 5 6
s 1
i 2
t 3
t 4
i 5
n 6
g 7
All the other values are built as the minimum of one of these three values:
lev(i-1, j) + 1
lev(i, j-1) + 1
lev(i-1, j-1) + 1_(a_i != b_i)
Where lev corresponds to the already existing levenshtein matrix elements.
The lev(i, j-1) is simply the matrix component to the left of the one, that we want to determine. lev(i-1, j) is the component above and lev(i-1, j-1) is the element left and above. Here, 1_(a_i != b_i) means, that if the letters on this space do not equal 1 is added, otherwise 0.
If we jump right into the matrix element (1, 1), wich corresponds to letters (s, k): We determine the 3 components:
lev(i-1, j) + 1 = 2 [1 + 1 = 2]
lev(i, j-1) + 1 = 2 [1 + 1 = 2]
lev(i-1, j-1) + 1 = 1 [0 + 1 = 1] + 1 because k is clearly not s
Now, we take the minimum of these three values and we found the next entry of the Levenshtein matrix.
Do this evaluation for each single element row OR columnwise and the result is the full Levenshtein matrix.
Hover your mouse above each value with the dots underneath in that matrix in the wikipedia article and it describes in layman's terms what each value means.
e.g. using (x,y) notation
element (0,0) compares None to None. (0,0) = 0 because they are equal
element (0,1) compares 'k' to None. (0,1) = 1 because:
insert 'k' to transform None to 'k' so +1
element (3,2) compares 'kit' to 'si'. (3,2) = 2 because of ``
None == None so +0 - Lev = 0 see element (0,0)
swap 's','k' so +1 - Lev = 1 see element (1,1)
'i' == 'i' so +0 - Lev = 1 see element (2,2)
insert 't' so +1 - Lev = 2 see element (3,2)
Related
The question asks to find an ith row and ith column such that the ith row only contains zeros, ane the ith column only contains ones (what is at their intersection doesn't matter) in linear time. If an i that satisfies this condition doesn't exist, just return -1. Here is the best I could come up with:
def zero_one(X):
X = numpy.array(X)
N = len(X)
for i in range(N):
original_value = X[i][i]
X[i][i] = 0
r = binaryToDecimal(X[i, :])
X[i][i] = 1
c = binaryToDecimal(X[:, i])
if r == 0 and c == 2**(N - 1) - 1:
X[i][i] = original_value
return i
X[i][i] = original_value
return -1 # in case there's no i that satisfies the condition
Assuming that binaryToDecimal() runs in linear time and column-wise like in NumPy is available, this could be linear, but I doubt it.
I believe it's doable in O(n) with a "tournament" strategy :
first we will eliminate all candidate but one, then we'll check if the last candidate is a valid answer.
I will give you a pseudo-code answer, because I don't know python, but it should be easy to implements.
make a variable "champion" containing the first index. (This variable will store the current winning index of the tournament).
For each other index j, match them against the champion index : if X[champion][j] is 0, then the champion stays, else champion becomes j
(If X[i][j] is a 1, then the ith row contains a 1 and i is not valid, and if it's a 0 then the jth column contains a 0, and is valid. Each match will thus eliminate one possible candidate.)
Check if the champion satifies the conditions : if so return the champion, else return -1. (All other indexes have been eliminated during 2) )
EDIT : Tried to add python code.
def zero_one(m):
n = len(m)
c = 0
for j in range(1,n):
if m[c][j] == 1:
c = j
for i in range(0,c-1):
if m[c][i] == 1 or m[i][c] == 0:
return -1
for i in range(c+1,n):
if m[c][i] == 1 or m[i][c] == 0:
return -1
return c
The complexity is 0(n) : you first check (n-1) element of the matrix during the tournament, and then check 2(n-1) element to validate the last index.
If you have any questions feel free to ask, I'll update accordingly.
I believe it is simpler than it seems. Consider that if row X holds all zeros (apart for the intersection with column X) then no other column Y!=X can hold all ones.
Hence we only need to check the rows: if we find an all-zeros (but the intersection) row X then we check the column X and just return X or -1 based on whether that column holds all ones (but the intersection). If no rows satisfy the criterion then we return -1 as well.
So the worst case is, we have to check N rows and 1 column.
def zero_one(mx):
n=len(mx)
for x in range(n):
if sum(mx[x])-mx[x][x] == 0:
return x if sum(list(zip(*mx))[x])-mx[x][x] == n-1 else -1
return -1
I am trying to solve a Dynamic programming problem which is as follows but unable to solve it.
You are given a primitive calculator that can perform the following three operations with the current number đť‘Ą: multiply đť‘Ą by 2, multiply đť‘Ą by 3, or add 1 to đť‘Ą. Your goal is given a positive integer đť‘›, find the minimum number of operations needed to obtain the number đť‘› starting from the number 1
I found the solution on stackoverflow itself but unable to understand what's going on.
I have heard that every DP problem can be solved by creating matrix which I was trying to do but don't know where I am going wrong. The table is created below which shows number of steps required to reach to n from 1, initially I take values as infinity.
i / j 0 1 2 3 4 5
plus 1 0 1 2 3 4 5
multiple by 2 0 infinity 2 infinity 3 infinity
multiple by 3 0 infinity infinity 2 infinity infinity
I am trying to solve this problem in Python.
Can someone please help me.
I found the solution which is as follows but not able to understand exactly what is going on:
import math
target = int(input())
def optVal(target, cache):
result = [1] * cache[-1] # 1
for i in range(1, cache[-1]): # 2
result[-i] = target # 3
if cache[target-1] == cache[target] - 1: # 4
target -= 1
elif target % 2 == 0 and (cache[target // 2] == cache[target] - 1): # 5
target //= 2
else: # 6 # target % 3 == 0 and (cache[target // 3] == cache[target] - 1):
target //= 3
return result
cache = [0] + [math.inf] * target # 1
for i in range(1, len(cache)): # 2
temp1 = math.inf
temp2 = math.inf
temp3 = math.inf
temp1 = cache[i - 1] + 1
if i % 2 == 0:
temp2 = cache[i // 2] + 1
if i % 3 == 0:
temp3 = cache[i // 3] + 1
cache[i] = min(temp1, temp2, temp3)
print('Minimum operation: ', cache[target] - 1)
finalLst = optVal(target, cache)
print(' '.join([str(x) for x in finalLst]))
Input:
5
Output:
3
1245
This algorithm is split in two parts. The first is in the main, the second is in the optVal function.
The first part builds the cache list, where cache[i] holds the minimum number of steps necessary to arrive from 0 to i applying, at each step, one of the three possible operations: +1, *2 or *3. This list is the 1-dimensional case of the matrix you read about.
When cache[i] is calculated, all indices lower than i already have been calculated. One can get to i in three possible ways, so a maximum of three possible sources of i, i.e., elements of cache, need to be examined: i-1, i//2 and i//3, but i//2 only if i is even, and i//3 only if i can be divided by 3. These elements of cache are compared, and the content of the winner, incremented by 1 (because of the extra step to get to i), is stored in cache. This process is bootstrapped by putting a 0 in cache[0]. In the end, cache[target] will contain the minimum number of steps to get to target starting from 0 (which is 1 more than the steps to get there starting from 1, which is how the problem was stated – note that you only can apply the +1 operation to move out from 0).
Now, if I had written the code, I probably would have stored the “parent” or the “winning operation” of each cache[i] together with the number of steps to get there (BTW, those math.inf are not really needed, because there always is a finite number of steps to reach i, because of the +1 operation.) The approach of the author is to infer this information from the content of the possible parents (max 3) of each cache[i] that needs to be examined. In both cases, the chain of “ancestors” has to be reconstructed backwards, starting from cache[target], and this is what happens in optVal().
In optVal() the target is changed at each iteration (a bit confusingly), because at each iteration the info you have is the minimum number of steps needed to reach a certain target number. Knowing that, you look at the 1, 2 or 3 possible parents to check which one contains exactly that number of steps minus 1. The one that passes the test is the actual parent, and so you can continue building the chain backwards replacing target with the parent.
to solve this DP, you have to construct a table of minimum number of steps required to get n, if one two or all the operations were available. you will be creating it left to right, top to bottom, ie 1 to n, add 1 to mul 3. As you go down more number of operations are available
A cells value only depends on the value above it (if available) and atmax 3 values in the left side eg. for (n = 6),(mul 3) cell will depend only on (n = 6),(mul 2) and (n = 2)(mul 3), (n = 3)(mul 3), (n = 5)(mul 3). you will then compare these values and whichever is smaller after operation, you will put that value, so you will be comparing value of (n = 2)(mul 3) + 1 vs (n = 3)(mul 3) + 1 vs (n = 5)(mul 3) + 1 vs (n = 6)(mul 2), and then whichever is smaller you will put that value
since n = 1 is given, the first column would have all the values as zero
for n = 2, its values will depend on values of n = 1. you can "add 1" or "multiply by 2" (1 step), both are valid. so this column will have all the values as 0 + 1 = 1
for n = 3, its values will depend on values of n = 1 (because 1 = 1/3 of 3) AND n = 2. if you can only "add 1" or "multiply by 2", then you will choose to add 1 to n = 2 so total steps 1+1 = 2. BUT if you could also multiply by three you will need only one step so 0 + 1 = 1. since 1 < 2 you will put 1 as this value. so the entries for n = 3 is 2, 2, 1
for n = 4, it will depend on n = 3 (add 1), and n = 2 (mul 2). so the values will be 3, 2, 2
for n = 5, it will depend on n = 4 (add 1). so the values will be 4, 3, 3
so the minimum steps are 3 to reach n = 5
final table:
1 2 3 4 5
add 1 0 1 2 3 4
mul 2 0 1 2 2 3
mul 3 0 1 1 2 3
#include <bits/stdc++.h>
using namespace std;
int rec(vector<int> &dp,int n)
{
if(n==1) return 0;
if(dp[n]!=INT_MAX) return dp[n];
return dp[n]=min({1+rec(dp,n-1),(n%2==0)?1+rec(dp,n/2):INT_MAX,(n%3==0)?1+rec(dp,n/3):INT_MAX});
}
string genseq(vector<int> &dp, int n){
string res="";
while(n>1)
{
res=to_string(n)+" "+res;
if(dp[n-1]==(dp[n]-1)) n--;
else if(n%2==0&&( dp[n/2]==dp[n]-1)) n/=2;
else if(n%3==0&&( dp[n/3]==dp[n]-1)) n/=3;
}
return "1 "+res;
}
int main()
{
int n;
cin>>n;
vector<int> dp(n+1,INT_MAX);
dp[0]=0;
dp[1]=0;
std::cout << rec(dp,n) << std::endl;
std::cout << genseq(dp,n) << std::endl;
return 0;
}
I'm quite new to Python coding and have difficulty understanding the following code below. It is on graph theory using DFS to find the largest area amongst all areas of islands. 1 represents an island and 0 represents water in a grid.
def maxAreaOfIsland(grid):
row, col = len(grid), len(grid[0])
def dfs(i, j):
if 0 <= i <= row - 1 and 0 <= j <= col - 1 and grid[i][j]:
grid[i][j] = 0
#scans through all rows & cols and
#turns number in the grid into 0 if all conditions are true?
return 1 + dfs(i - 1, j) + dfs(i + 1, j) + dfs(i, j - 1) + dfs(i, j + 1)
return 0
# recursive function that checks up, down, left, right in the grid.
# when does it return 1?
return max(dfs(i, j) for i in range(row) for j in range(col))
maxAreaOfIsland([[1,0,1,1,1],
[0,0,0,1,1],
[1,1,1,0,1]])
Out: 6
I have included comments, which reflect my understanding so far, but not sure if it's correct. I'm quite confused from line 4 onwards, particularly the recursive part.
Could someone explain in detail? Typically these kind of codes tend to have a queue/dequeue to record whether the island has been visited, but I don't think this code has that?
I guess the question is really about understanding algorithm not Python. Provided Python code is pretty easy.
The code contains function maxAreaOfIsland which in turn comtains recursive function dfs. These 2 functions form 2 layers of computation. Lets look at those layers separately.
# outer layer
def maxAreaOfIsland(grid):
row, col = len(grid), len(grid[0])
# function dfs() definition
return max(dfs(i, j) for i in range(row) for j in range(col))
So outer layer is very simple - compute dfs(i, j) for all possible i and j then choose maximum computed value.
# inner layer - slightly modified
def dfs(i, j):
# recursive case
if (0 <= i <= row - 1 and 0 <= j <= col - 1) and grid[i][j] == 1:
grid[i][j] = 0 # this is how we remember visited cells since we don't count zeros
# optional prints to look at the grid during computation
# print(i, j)
# print(*grid, sep='\n', end='\n\n')
count_current = 1
count_neighbors = dfs(i - 1, j) + dfs(i + 1, j) + dfs(i, j - 1) + dfs(i, j + 1)
return count_current + count_neighbors
# trivial case and out-of-borders case
else:
return 0
Inner layer is a liitle bit more complicated. What it does? (1) It gets i and j. (2) If the cell contains 0 then it's trivial case (water) or we are out of the grid - just return 0. (3) If the cell contains 1 then it's recursive case (land) - function starts to count amount of all the 1 adjacent to the given cell with every 1 counted turning into 0 to avoid double counting.
Your sample grid has 3 rows (0, 1, 2) and 5 columns (0, 1, 2, 3, 4). Suppose we are at i = 0, j = 2. It is 1. We count it (current result is 1), turn it into 0 and look at its neighbors one by one - upper neighbor is out of the grid, bottom neighbor is 0, left neighbor is 0, right neighbor is 1. We dont return current result but proceed to the right neigbor i = 0, j = 3. We count it (cuurent result is 2), turn it into 0 and look at neighbors. Upper neighbor is out of the grid, bottom neighbor is 1. We stop here, we dont return current result, we remember about 2 more neighbors, we proceed to the bottom neighbor i = 1, j = 3. We count it (current result is 3), turn it into 0 and look at neighbors. Upper neighbor is 1. We stop here, we dont return current result, we remember about 3 more neighbors, we proceed to the upper neighbor i = 0, j = 3. And so on.
My advice is to draw simple sample grid (with a pen on a piece of paper) and manually apply dfs algorithm to it.
I'm trying to code the game connect-4, and there is a part of my code in which i try to find in a 7x6 matrix, diagonals of 4 ones in a row or 4 2s in a row.
This part of my code does not work i tried everything I was able to. And sometimes it detects that there is a 4 1s or 4 2s diagonal where is not. I created the matrix puting a 7 zero list in each position of a 6 zeros lists. I'm trying to do it using only lists functions, i cant use the numpy library or similar.
Okay, in this part of the code I'm trying to find if in each possible diagonal of the matrice there are 4 zeros in a row. PD: I'm only trying to find the diagonals that go from left to right ATM. Thanks for your help, I tried to explain my problem as good as I can because english is not my main tongue.
This is my code:
import random
llista = [0]*6 #when i say llista y mean matrix
for i in range(6):
llista[i]=[0]*7
#Here i fill the 7*6 matrix of 0s 1s and 2s randomly so i can see if it works.
for i in range(30):
x=random.randrange(-1,-7,-1)
y=random.randrange(0,7,1)
llista[x][y]=1
for i in range(30):
x=random.randrange(-1,-7,-1)
y=random.randrange(0,7,1)
llista[x][y]=2
#This 2 loops here are too see if it is possible to have a diagonal in the matrece because if you want a diagonal u need at least a one or 2 in the center, the problem is not here.
for i in range(-1,-7,-1):
possible = False
if llista[i][3]==1:
possible = True
break
for i in range(7):
possible2 = False
if llista[-4][i]==1 or llista[-4][i]==1:
possible2=True
break
if possible==True and possible2==True:
#The problem starts here. This first loop i use it too find the diagonals that go from left to right. I want to find diagonals of 4 1s or 4 2s.
for i in range(len(llista)-3):
for j in range(len(llista[i])-3):
#This if is too see if we have four 1 or 2 togheter in the list, if we have them it prints the sentence below.
if (llista[i][j]==1 and llista[i+1][j+1]==1 and llista[i+2][j+2]==1 and llista[i+3][j+3]==1) or (llista[i][j]==2 and llista[i+1][j+1]==2 and llista[i+2][j+2]==2 and llista[i+3][j+3]==2 ):
print("There is at least one left to right diagonal")
#This loop is the same than the last one but to find diagonals from right to left (a 4 diagonal made of 1s or 2s)
for i in range(len(llista)):
for j in range(len(llista[i])):
if i-3<0 and j-3<0:
if (llista[i][j]==1 and llista[i-1][j-1]==1 and llista[i-2][j-2]==1 and llista[i-3][j-3]==1) or (llista[i][j]==2 and llista[i-1][j-1]==2 and llista[i-2][j-2]==2 and llista[i-3][j-3]==2 ):
print("There is at least one right to left diagonal")
#Here i print the matrix
for i in range(6):
print(llista[i])
#So this program should say if there is at least one left to right diagonal
or right to left diagonal.
#I dont want to use functions that are not being used already, and i dont wanna do it another way because i must understand this way. thanks
If you consider the logic of your 'right-to-left' loop, you are actually just doing the same as your 'left-to-right' loop in reverse order. To really get the 'right-to-left' pass right you have to have your i and j indices moving in different directions.
So your conditional statement in this section should look like:
if i-3>=0 and j+3<7:
if (llista[i][j]==1 and llista[i-1][j+1]==1 and llista[i-2][j+2]==1 and llista[i-3][j+3]==1) or (llista[i][j]==2 and llista[i-1][j+1]==2 and llista[i-2][j+2]==2 and llista[i-3][j+3]==2 ):
print("There is at least one right to left diagonal")
There are a ton of optimizations you could use by importing libraries like numpy or itertools as AResem showed. That answer is not entirely correct though for the following reason.
When you say return True, k you are not exercising any control over the value of k because it was used in the list comprehension just above and will just have the value of the last item it iterated over. So when your function finds a diagonal it reports the wrong number about two thirds of the time.
Here is an edited function that gives the correct results:
def check_diagonals(matrix):
for offset in range(-2, 4):
diag = matrix.diagonal(offset=offset)
# Here you can create a tuple of numbers with the number of times they are repeated.
# This allows you to keep your k and g values associated.
repeat_groups = [(k, sum(1 for _ in g)) for k, g in groupby(diag)]
# By using the built-in max function with the 'key' keyword, you can find
# the maximum number of repeats and return the number associated with that.
num, max_repeats = max(repeat_groups, key=lambda item: item[1])
if max_repeats >= 4:
return True, num
return False, None
If you run this function with print statements added you can get output like the following:
Matrix:
[[1 0 2 2 1 0 1]
[0 2 0 2 1 1 1]
[2 2 0 0 0 0 1]
[0 0 2 2 0 2 2]
[2 1 1 1 1 1 0]
[2 2 0 2 1 0 2]]
offset -2
diag [2 0 1 2]
repeat_groups [(2, 1), (0, 1), (1, 1), (2, 1)]
num, max_repeats 2 1
offset -1
diag [0 2 2 1 1]
repeat_groups [(0, 1), (2, 2), (1, 2)]
num, max_repeats 2 2
offset 0
diag [1 2 0 2 1 0]
repeat_groups [(1, 1), (2, 1), (0, 1), (2, 1), (1, 1), (0, 1)]
num, max_repeats 1 1
offset 1
diag [0 0 0 0 1 2]
repeat_groups [(0, 4), (1, 1), (2, 1)]
num, max_repeats 0 4
(True, 0)
There is at least one left to right diagonal: 0's' # Correct!
If you want to ignore diagonals of zeros, you can easily add an extra condition, e.g.
if max_repeats >= 4 and num != 0:
return True, num
You could try and recreate this without using numpy if you wanted.
Perhaps you are not getting the right answer because of the way you parsed your conditional statements.
You should have
if cond1 or cond2:
# do something
with the conditions contained in parentheses (). At the moment only your second condition is contained in parentheses.
Try the following:
if (matrix[i][j]==1 and matrix[i+1][j+1]==1 and matrix[i+2][j+2]==1 and matrix[i+3][j+3]==1) or (matrix[i][j]==2 and matrix[i+1][j+1]==2 and matrix[i+2][j+2]==2 and matrix[i+3][j+3]==2 ):
print("There is at least one left to right diagonal")
You may consider using numpy for this problem. Here goes some code to get you started.
import numpy as np
from itertools import groupby
def check_diagonals(matrix):
for offset in range(-2, 4):
diag = matrix.diagonal(offset=offset)
if max([sum(1 for _ in g) for k, g in groupby(diag)]) >= 4:
return True, k
return False, None
# random test matrix
matrix = np.random.randint(0, 3, 6 * 7)
matrix = matrix.reshape(6,7)
# left to right check
resp_tuple = check_diagonals(matrix)
if resp_tuple[0]:
print("There is at least one left to right diagonal: {}'s'".format(resp_tuple[1]))
else:
# right to left
resp_tuple = check_diagonals(np.fliplr(matrix))
if resp_tuple[0]:
print("There is at least one right to left diagonal: {}'s'".format(resp_tuple[1]))
else:
# No diagonals
print('No diagonals')
class Solution:
def solveNQueens(self, n):
def n_queens_solver(row, visited_cols, unique_y_intercepts, res):
if row == n:
results.append(res)
return
for col in range(n):
if col not in visited_cols and (row + col) not in unique_y_intercepts and (col - row) not in unique_y_intercepts:
visited_cols_dup = visited_cols.copy()
unique_y_intercepts_dup = unique_y_intercepts.copy()
res_dup = res.copy()
visited_cols_dup.add(col)
unique_y_intercepts_dup.add(row + col)
unique_y_intercepts_dup.add(col - row)
this_row = '.' * col + 'Q' + '.' * (n - col - 1)
res_dup.append(this_row)
n_queens_solver(row + 1, visited_cols_dup, unique_y_intercepts_dup, res_dup)
results = []
n_queens_solver(0, set(), set(), [])
return results
I haven't yet looked at an actual solution for this problem, and I imagine mine is pretty damn inefficient, but I don't know what I'm doing wrong.
Sample input:
n = 4
Correct output:
[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
My output:
[]
To account for unique diagonals, I figured for every valid place to insert a queen, we need to account for all lines with slope +1 and slope -1. Each of these lines has a unique y-intercept. Using y=x+b and y=-x+b, every potential point to insert a queen has to not have (y-x == b) or (y+x == b).
Anything glaringly incorrect with my rationale here?
Note - I'm not asking for a different or more optimal solution. Am only trying to figure out where my thought process is incorrect.
The mistake in the algorithm is as follows. Look at what happens when you try to mark diagonals as visited.
Let's draw the 4x4 board and assign each cell the number of positive-sloped diagonal it is located on (put i + j on the square located in the row i and col j):
0 1 2 3
1 2 3 4
2 3 4 5
3 4 5 6
Suppose that you put the first queen on the position (1,3). I know that your algorithm starts with row 0, but it doesn't matter in this case. Now the board looks as follows:
0 1 2 3
1 2 3 Q
2 3 4 5
3 4 5 6
Then you add 3 to visited_cols, add 3 + 1 = 4 to y_intercepts and add 3 - 1 = 2 to y_intercepts. We have cols = {3} and y_intercepts = {2,4}. Let's mark with X on the board the diagonal corresponding to the value 2 of y_intercept:
0 1 X 3
1 X 3 Q
X 3 4 5
3 4 5 6
Now suppose we proceed with algorithm to row 2 and we try to put the second queen on square (2,0). This is a valid position because the first queen doesn't attack this square. But your algorithm will reject this position, because row + col = 2 + 0 = 2 is in the y_intercepts set. What happened? We did a positive-slope test for the square (2, 0) and it failed because there was 2 in the y_intercepts set. But note that this 2 was added there after checking the negative-sloped diagonal (remember 3 - 1 = 2 ?). So the tests for positive-sloped and negative-sloped diagonals got mixed which resulted in the incorrect rejection of square (2, 0). This is the reason why your program outputs the empty results vector - at some point of the algorithm there is a row such that all its squares are rejected (some are rejected correctly and others are rejected incorrectly similarly to what we just observed).
One way to fix it is to create two separate sets for positive-sloped diagonals and negative-sloped diagonals and check row + col for positive-sloped ones and col - row for negative ones.