changing n queens problem with backtracking - python

I have an N queen program with backtracking (it generates all the possible solutions) that I want to change it in a way that it places the queens in the half of each column and half of each row(number of columns and rows are even). for example if I have 6 columns and 4 rows it puts 2 queens in each row and 3 queens in each column.
Output example:
[[1 0 1 0 0 1]
[0 1 0 1 1 0]
[1 0 1 0 0 1]
[0 1 0 1 1 0]]
The problem is when I run my script I get this error:
IndexError: index 4 is out of bounds for axis 0 with size 4
I don't know which part I'm doing wrong.
here is my code:
k = 1
global N
t=4
N=t-1
w=(t-1)*2
def printSolution(board):
global k
print(k, "-\n")
k = k + 1
for i in range(N*2):
for j in range(N*2):
print(board[i][j], end = " ")
print("\n")
print("\n")
def isSafe(board, row, col) :
for i in range (row):
for j in range(col):
if np.sum(board[i][j])>N:
return False
for j in range (col):
for i in range(row):
if np.sum(board[i][j])> int(t/2):
return False
return True
def solveNQUtil(board,row, col) :
if col>=w and row<t:
col=0
row+=1
if (col == w and row==t):
printSolution(board)
return True
res = False
for i in range(N):
if (isSafe(board, row, col)):
board[row][col] = 1;
res = solveNQUtil(board, row,col+1 ) or res;
return res
def solveNQ() :
board = np.zeros((t,w))
if (solveNQUtil(board, 0,0) == False):
print("Solution does not exist")
return
return
solveNQ()

If you hit the last element on the board, you will have col = w and row = t-1. So in solveNQUtil you will enter the first block and set col = 0 and row = t. Then, in the next check you don't have col == w but col = 0. So you continue and later attempt to access board[row] which is then of course out of bounds.
I guess the test whether you reached the end should be the first thin in solveNQutil and should read something like if col == w and row == t - 1?

Related

how to write a python code to display magic square matrix according to user input?

This is a program to print a matrix whose sum of each row , column or diagonal elements are equal.
I have a working code but my program gives same output each time i run it. I need a program to print different matrix output for same input.
def matrix(n):
m = [[0 for x in range(n)]for y in range(n)]
i = n // 2
j = n - 1
num = 1
while num <= (n * n):
if i == -1 and j == n:
j = n - 2
i = 0
else:
if j == n:
j = 0
if i < 0:
i = n - 1
if m[int(i)][int(j)]:
j = j - 2
i = i + 1
continue
else:
m[int(i)][int(j)] = num
num = num + 1
j = j + 1
i = i - 1
print ("Sum of eggs in each row or column and diagonal : ",int(n*(n*n+1)/2),"\n")
for i in range(0, n):
for j in range(0, n):
print('%2d ' % (m[i][j]),end = '')
if j == n - 1:
print()
n=int(input("Number of rows of the matrix : "))
matrix(n)
I am unsure whether this is what you are looking for, but one solution is to add a random number to each value of the matrix, as this doesn't break the property
a matrix whose sum of each row, column or diagonal elements are equal.
Here is how you could do it:
add = random.randint(0, 50)
m = [[v+add for v in row] for row in m]
Moreover, you can rotate and add two magic squares without loosing their property. Therefore, you can rotate the magic square you have and add it to the original. This can add some nonlinearity to the results.
def rotate(m): # 90 degrees counter clockwise
return [[m[j][i] for j in range(len(m))] for i in range(len(m[0])-1, -1, -1)]
# add the matrix with its rotated version
m = list(map(lambda e: [sum(x) for x in zip(*e)], zip(m, rotate(m))))
I hope this helps!

Given a bigger matrix and a smaller matrix check if the smaller matrix can be found in bigger matrix in python

sample input:
3(int)
1 1 1
2 2 2
3 3 3 #(matrix)
2(int)
1 1
2 2#(matrix)
enter code here
a = int(input())
for i in range(a):
l = list(map(int,input().split())
b = int(input())
for j in range(b):
l1 = list(map(int,input().split())
if l1 in l:
print("true")
else:
print("False")
it needs to show "true" but it always show "False".
The in operator doesn't work in your case. You must iterate over each value of your bigger matrix, check if the value corresponds to the first value of the smaller matrix and then, if True, check if all the following values correspond to the values of the smaller matrix.
def is_matrix_contained(bigger: list[list[int]], smaller: list[list[int]]) -> bool:
for row_ind, row in enumerate(bigger[:len(bigger) - len(smaller) + 1]):
for col_ind, col in enumerate(row[:len(bigger) - len(smaller) + 1]):
if col == smaller[0][0]:
is_contained = True
for i in range(len(smaller)):
for j in range(len(smaller[0])):
if bigger[row_ind + i][col_ind + j] != smaller[i][j]:
is_contained = False
break
if not is_contained: break
if is_contained: return True
else: break
return False
This will take 2D lists as parameter, so you will have to change the way you get inputs from user :
a = int(input())
l = [[int(i) for i in input().split()] for _ in range(a)]
b = int(input())
l1 = [[int(i) for i in input().split()] for _ in range(b)]
if is_matrix_contained(l, l1):
print("true")
else:
print("false")

How would I implement backtracking here?

I've been struggling to find the right logic for my sudoku solver. So far I've created a function to take (x,y) coordinates and the number and check if it is a legal move.
Though I don't understand how I can iterate through the grid replacing every 0 with a legal number, then go back and fix numbers that make the solve incorrect.
For example sometimes I will be left with 0's on the grid because some numbers can no longer be played. I took a deeper look at it and realized that numbers played previously in the same row were legal but ruined the puzzle. Instead, if those numbers were a bit higher the puzzle would be solved.
I understand backtracking would be my friend here but, I have no clue on how to implement it. So far here is what I have.
solve.py
import numpy as np
import time
class sodoku:
def __init__(self,grid,boxRange):
self.grid = grid
self.boxRange = boxRange
def show(self):
for row in self.grid:
print(row)
def solve(self):
def possible(num,x,y):
def box(x,y):
board = np.array(self.grid)
result = {}
size = 3
for i in range(len(board) // size):
for j in range(len(board) // size):
values = board[j * size:(j + 1) * size, i * size:(i + 1) * size]
result[i * size + j + 1] = values.flatten()
if y <= 2 and x <= 2:
squareBox = result[1]
if (y <= 5 and y > 2) and x <= 2:
squareBox = result[2]
if (y <= 8 and y > 5) and x <= 2:
squareBox = result[3]
if (y <= 2 ) and (x <= 5 and x > 2):
squareBox = result[4]
if (y <= 5 and y > 2)and (x <= 5 and x > 2):
squareBox = result[5]
if (y <= 8 and y > 5)and (x <= 5 and x > 2):
squareBox = result[6]
if (y <= 2) and (x <= 8 and x > 5):
squareBox = result[7]
if (y <= 5 and y > 2)and (x <= 8 and x > 5):
squareBox = result[8]
if (y <= 8 and y > 5)and (x <= 8 and x > 5):
squareBox = result[9]
return squareBox
row = self.grid[y]
column= [r[x] for r in self.grid]
square = box(x,y)
if (num not in row) and (num not in column) and (num not in square):
return True
else:
return False
y = 0
for row in self.grid:
x = 0
for number in row:
if number == 0:
for i in range(1,10):
if possible(i,x,y):
row[x] = i
elif i == 9 and possible(i,x,y) == False: pass
#what would I do here now
x += 1
y += 1
boxRange = "3x3"
bxd = []
with open('board.txt', 'r') as f:
for line in f:
line = line.strip()
line = line.split(' ')
bLine = [int(x) for x in line]
bxd.append(bLine)
# brd = [[3,0,0,2],[0,4,1,0],[0,3,2,0],[4,0,0,1]]
brd = sodoku(bxd,boxRange)
brd.show()
brd.solve()
print('-----Solved------')
brd.show()
board.txt
5 3 0 0 7 0 1 0 0
6 0 0 1 9 5 0 0 0
0 9 8 0 0 0 0 6 0
8 0 0 0 6 0 0 0 3
4 0 0 8 0 3 0 0 1
7 0 0 0 2 0 0 0 6
0 6 0 0 0 0 2 8 0
0 0 0 4 1 9 0 0 5
0 0 0 0 8 0 0 7 9
Recursive pseudocode backtracing sudoku solver:
#solve will return a solved board, or None if it fails
def solve(board):
#case 1: board is solved
if board.is_solved: #simple check for leftover empty spaces
return board #board is solved. unzip the call stack
pos = board.next_empty_space()
valid = [i for i in range(1,10) if board.is_valid(pos, i)]
#case 2: not solved and no more valid moves
if not valid:
return None #no valid moves left
new_board = copy(board) #don't step on the original data in case this isn't the solution
for value in valid:
new_board[pos] = value
result = solve(new_board)
#case 3: one of the valid moves led to a valid solution
if result is not None: #we found a fully solved board
return result #here's where we unzip the call stack
#case 4: none of the valid moves led to a valid solution
return None #none of the valid moves panned out
Basically you consider each empty space on the board as a branch in a tree, and sub-branches from each branch you insert a new number which is currently valid at that point in the tree. If you get to the end of a branch, and there are no more valid moves left (sub-branches) you have either successfully filled in all the blank spaces or one of the numbers is wrong. When None gets returned, and execution goes back to the caller (up a frame in the call stack), the local position in the for loop going over valid moves is what "remembers" where you're at, and what the next possible valid move should be. It's basically a depth-first tree search algorithm for a correct board state.

Hackerrank diagonal difference, what's wrong with my code?

Given a square matrix, calculate the absolute difference between the sums of its diagonals.
For example, the square matrix is shown below:
1 2 3
4 5 6
9 8 9
The left-to-right diagonal =1 + 5 + 9 = 15 . The right to left diagonal =3+5+9=17 . Their absolute difference is |15-17|=2.
Function description
Complete the diagonalDifference function in the editor below. It must return an integer representing the absolute diagonal difference.
diagonalDifference takes the following parameter:
arr: an array of integers .
Input Format
The first line contains a single integer,n , the number of rows and columns in the matrix arr.
Each of the next n lines describes a row,arr[i] , and consists of n space-separated integers arr[i][j] .
Sample Input
3
11 2 4
4 5 6
10 8 -12
Sample Output
15
My code:
def diagonalDifference(arr):
i = 0
j = 0
left = 0
right = 0
for x in range(arr+1):
left += arr[0 + i][0 + j]
right += arr[0 + i][n - j]
i += 1
j += 1
return abs(left - right)
Here's my code. I don't know what's wrong. Please help.
The Question is "Diagonal Difference" on Hackerrank.
EDIT: Second attempt
def diagonalDifference(arr):
left = 0
right = 0
for x in range(len(arr)):
left += arr[0+x][0+x]
right += arr[0+x][len(arr)-x]
return abs(left-right)
I get following error:
right += arr[0+x][len(arr)-x]
IndexError: list index out of range
You cannot access len(arr)-x - for x == 0 this is IndexError :
def diagonalDifference(arr):
left = 0
right = 0
for x in range(len(arr)):
left += arr[0+x][0+x]
right += arr[0+x][len(arr)-x]
return abs(left-right)
arr = [[1,2],[3,4]]
len_arr = len(arr) # len(arr) is 2, you index into arr[0][2-0] fox x==0
# but arr only has arr[0][0] and arr[0][1] for x == 0
You need to sum over:
k[0][0], k[1][1], k[2][2], ..., k[n-1][n-1] where n = len(k) for the forward diag
and
k[0][n-1-0], k[1][n-1-1], k[2][n-1-2], ..., k[n-1][n-1-(n-1)] for the backward diag
Codewise:
def diag (data, reverse=False):
ld = len(data)
if reverse:
return sum(data[i][ld-i-1] for i in range(ld))
else:
return sum(data[i][i] for i in range(ld))
k = [[0,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20],[0,22,23,24,25]]
print (diag(k)) # 64
print(diag(k,True)) # 44
def absDiagDiff(data):
return abs(diag(data)-diag(data,True))
print(absDiagDiff(k)) # 20
#!/bin/python3
import math
import os
import random
import re
import sys
#
# Complete the 'diagonalDifference' function below.
#
# The function is expected to return an INTEGER.
# The function accepts 2D_INTEGER_ARRAY arr as parameter.
#
def diagonalDifference(arr):
diag1=0
diag2=0
for x in range(int(len(arr))):
y=list(reversed(list(range(len(arr[x])))))
diag1+=arr[x][x]
diag2+=arr[x][y[x]]
return abs(diag1-diag2)
if __name__ == '__main__':
fptr = open(os.environ['OUTPUT_PATH'], 'w')
n = int(input().strip())
arr = []
for _ in range(n):
arr.append(list(map(int, input().rstrip().split())))
result = diagonalDifference(arr)
fptr.write(str(result) + '\n')
fptr.close()
If that can help, here's how I would of done it :
n = int(input())
array = []
total1 = 0
total2 = 0
index = 0
for i in range(n):
array = [[] for n in range(n)]
for arrays in array:
arrays += map(int,input().split())
if len(arrays) != n:
print(f"Error, need to be {n} by {n}")
if index == 0:
for arrays in array:
total1 += arrays[index]
index += 1
elif index == n:
for arrays in array:
total2 += arrays[index-1]
index -= 1
print(abs(total1-total2))

Best way to compute amount of neighbours in matrix?

I need to write a function def amountofNeighbours(row, column) that prints the amount of neighbours there are to a certain element in the matrix. For example, given the matrix [[2, 3, 4], [5, 6, 7], [8, 9, 10]], there are three neighbours to the element 2 at position [0][0], while there are eight neighbours to the element 6 at position [1][1]. I'm not sure what is the best way to handle a problem like this. I went through all the possibilities, and this gave me the following:
def amountofNeighbours(row, column):
neighbours = 0
for i in range(row):
for j in range(column):
if i == 0 and j == 0 or i == 0 and j == column - 1:
neighbours = 3
elif i == row - 1 and j == 0 or i == row-1 and j == column - 1:
neighbours = 3
elif i > 0 and j == 0 or i == 0 and j > 0:
neighbours = 5
elif i == row - 1 and j > 0:
neighbours = 5
elif j == column - 1 and i > 0:
neighbours = 5
else:
neighbours = 8
return neighbours
When I called this with amountofNeighbours(1, 1) it gave me the correct answer, namely 3, but if I called it with amountofNeighbours(2,2) the answer should be 8 while it gave me 3. Anyone has an idea for improvement?
A straight forward way to do it is to say, "If the cell is at corner, it has three neighbors, otherwise if it is on an edge, it has five, otherwise it has 8."
def numberOfNeighbors(rows, columns, row, column):
topBottom = row in (0, rows-1)
leftRight = column in (0, columns-1)
if topBottom and leftRight:
return 3
if topBottom or leftRight:
return 5
return 8
Your function as it is designed now does not do what you specified. It takes in the number of rows and columns. Then it loops through all elements of your matrix and calculates the number of neighbours. Then it returns the last value calculated, so the bottom right element of your matrix, which has 3 neighbours indeed.
You should get rid of the loops to get it to do what you want. To clarify:
def amountofNeighbours(row, column, n_rows, n_cols):
neighbours = 0
if row == 0 and column == 0 or row == 0 and column == n_cols - 1:
neighbours = 3
elif row == n_rows - 1 and column == 0 or row == n_rows-1 and column == n_cols - 1:
neighbours = 3
elif row > 0 and column == 0 or row == 0 and column > 0:
neighbours = 5
elif row == n_rows - 1 and column > 0:
neighbours = 5
elif column == n_cols - 1 and row > 0:
neighbours = 5
else:
neighbours = 8
return neighbours
One solution to avoid many IFs is to start from the element and compute an "enlarged" box around it (a 3x3 square) possibly placed partially outside the matrix.
Then you clamp the result and return the number of elements minus one:
def neighbors(row, col, rows, cols):
ra, rb = row-1, row+2
ca, cb = col-1, col+2
dx = min(cb, cols) - max(0, ca)
dy = min(rb, rows) - max(0, ra)
return dx*dy - 1
The image shows the selected element and the enlarged box around it. The min/max operation will cut off the extra squares leaving a 2x3 box resulting in 2*3-1=5 neighbors count.

Categories

Resources