What's wrong in my N-Queens solution? - python

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.

Related

Find minimum steps required to reach n

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;
}

Find diagonals in a Python matrix using lists

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')

How to change this recursive function (return a list of paths for a 3X3 matrix) into iterative function in Python 2.7?

the recursive function below helps to find all the paths for a 3X3 matrix, from top left to bottom right, moving either down or right. But i want to change it into an iterative function so that I can edit the function to just find a specific completed path (just 1, from top left to bottom right, by moving right or down) which sums up( sum of the values at each point equate to a set number) to a desired number eg. 12. This is especially important for a bigger matrix eg. a 9 X 1000 matrix. How do I do it?
Note for Danoran:
The values are always positive. If you look at my 3X3 matrix a, you see values of 1s, 2s and 3s. So for example, moving from 1 to 1 to 1 to 2 to 3 (goal) is a completed path and the sum is 8.
This finds all the paths only.
a = []
for i in range(3):
r = []
for j in range(3):
r.append(i+1)
a.append(r)
a = matrix
1 1 1
2 2 2
3 3 3
all_paths = []
def printall(currentRow, currentColumn, nums):
if (currentRow == len(a) - 1):
for i in range(currentColumn, len(a[0])):
nums.append(a[currentRow][i])
all_paths.append(nums)
return all_paths
if (currentColumn == len(a[0]) - 1):
for i in range(currentRow, len(a)):
nums.append(a[i][currentColumn])
all_paths.append(nums)
return all_paths
nums.append(a[currentRow][currentColumn])
printall(currentRow+1, currentColumn, nums[:])
printall(currentRow, currentColumn+1, nums[:])
printall(0,0,[])
print all_paths
If there are R rows and C columns, you have to make R-1 down-jumps and
C-1 right-jumps. That’s invariant. The only variation is in the order of
the jumps. If we say dj=R-1 and rj=C-1, then the total number of paths
is (dj+rj)!/(dj!rj!).
So, we can simply iterate through all the unique permutations. Note that
itertools.permutations() will generate all permutations, not just
the unique ones, so we have to filter out the repeats. Of course, this
also means the run time will be proportional to (dj+rj)!, the number of
non-unique permutations. I won’t go into how to efficiently generate
unique permutations; see, for example, Question 22431637.
In the code below, I’ve increased the number of rows to 4, to help
distinguish rows from columns.
from itertools import permutations
a = []
for i in range(4):
r = []
for j in range(3):
r.append(i+1)
a.append(r)
#print a # Uncomment to trace execution
all_paths = []
def gen_all_paths(matrix):
rows = len(matrix)
cols = len(matrix[0])
dj = rows - 1 # down-jumps
rj = cols - 1 # right-jumps
pathmix = 'd' * dj + 'r' * rj
prev = ()
for path in permutations(pathmix):
if path <= prev: # filter out repeats
continue
prev = path
r, c = 0, 0
cells = [matrix[0][0]]
for i in path:
if i == 'd':
r += 1
else:
c += 1
cells.append(matrix[r][c])
#print ''.join(path), cells # Uncomment to trace execution
all_paths.append(cells)
gen_all_paths(a)
print all_paths

levenshtein matrix cell calculation

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)

Python find max number of combinations in binary

Hi I'm trying to figure out a function where given a length n of a list [x1, x2... xn], how many digits would be needed for a base 2 number system to assign a unique code to each value in the list.
For example, one digit can hold two unique values:
x1 0
x2 1
two digits can hold four:
x1 00
x2 01
x3 10
x4 11
etc. I'm trying to write a python function calcBitDigits(myListLength) that takes this list length and returns the number of digits needed. calcBitDigits(2) = 1, calcBitDigits(4) = 2, calcBitDigits(3) = 2, etc.
>>> for i in range(10):
... print i, i.bit_length()
0 0
1 1
2 2
3 2
4 3
5 3
6 3
7 3
8 4
9 4
I'm not clear on exactly what it is you want, but it appears you want to subtract 1 from what bit_length() returns - or maybe not ;-)
On third thought ;-), maybe you really want this:
def calcBitDigits(n):
return (n-1).bit_length()
At least that gives the result you said you wanted in each of the examples you gave.
Note: for an integer n > 0, n.bit_length() is the number of bits needed to represent n in binary. (n-1).bit_length() is really a faster way of computing int(math.ceil(math.log(n, 2))).
Clarification: I understand the original question now ;-) Here's how to think about the answer: if you have n items, then you can assign them unique codes using the n integers in 0 through n-1 inclusive. How many bits does that take? The number of bits needed to express n-1 (the largest of the codes) in binary. I hope that makes the answer obvious instead of mysterious ;-)
As comments pointed out, the argument gets strained for n=1. It's a quirk then that (0).bit_length() == 0. So watch out for that one!
Use the following -
import math
int(math.ceil(math.log(x,2)))
where x is the list length.
Edit:
For x = 1, we need to have a separate case that would return 1. Thanks #thefourtheye for pointing this out.
I am not comfortable with the other answers, since most of them fail at the corner case (when n == 1). So, I wrote this based on Tim's answer.
def calcBitDigits(n):
if n <= 0: return 0
elif n <= 2: return 1
return (n-1).bit_length()
for i in range(10):
print i, calcBitDigits(i)
Output
0 0
1 1
2 1
3 2
4 2
5 3
6 3
7 3
8 3
9 4
x = int(log(n,2))+1
x will be the number of bits required to store the integer value n.
If for some reason you don't want to use .bit_length, here's another way to find it.
from itertools import count
def calcBitDigits(n):
return next(i for i in count() if 1<<i >= n)

Categories

Resources