How do you make a checkerboard? - python

I need to make a checkerboard using only 1 and 0's by using lists to make a grid. I have created a code that creates an 8 by 8 grid of 0's. Then I attempt to use a nested for loop to fill it in, what am I doing wrong?
board = []
def print_board(board):
for i in range(8):
board.append([0]*8)
for i in range(len(board)):
for j in range(len(board[i])):
if i == 0 or i == 2 or i == 4 or i == 6 and j == 1 or j == 3 or j==5 or j==7:
board[i][j] = 1
elif i == 1 or i ==3 or i == 5 or i == 7 and j == 0 or j == 2 or j==4 or j==6:
board[i][j] = 1
for i in range(len(board)):
print(board[i])
print_board(board)
Why are the if and elif statements not working?

To make a checkerboard, a simple strategy is to check the parity of rows/cols.
If identical, set to 1 (or 0), if different, set the other way around.
This can be achieved with a simple list comprehension:
def board(n=8):
return [[int(i%2==j%2) for i in range(n)] # converting True to 1 directly
for j in range(n)]
output:
board(8)
[[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1]]
board(5)
[[1, 0, 1, 0, 1],
[0, 1, 0, 1, 0],
[1, 0, 1, 0, 1],
[0, 1, 0, 1, 0],
[1, 0, 1, 0, 1]]

The reason that the code doesn't work is that the interpreter treats:
i == 0 or i == 2 or i == 4 or i == 6 and j == 1 or j == 3 or j==5 or j==7:
as
((i == 0 or i == 2 or i == 4 or i == 6) and j == 1) or j == 3 or j==5 or j==7:
i.e. it starts from the left and evaluates each operator one by one.
You can correct your code by replacing:
if i == 0 or i == 2 or i == 4 or i == 6 and j == 1 or j == 3 or j==5 or j==7:
board[i][j] = 1
elif i == 1 or i ==3 or i == 5 or i == 7 and j == 0 or j == 2 or j==4 or j==6:
board[i][j] = 1
With:
if (i == 0 or i == 2 or i == 4 or i == 6) and (j == 1 or j == 3 or j==5 or j==7):
board[i][j] = 1
elif (i == 1 or i ==3 or i == 5 or i == 7) and (j == 0 or j == 2 or j==4 or j==6):
board[i][j] = 1
Or replace it with this condition
if i % 2 == 0 and j % 2 != 0:
board[i][j] = 1
elif i % 2 != 0 and j % 2 == 0:
board[i][j] = 1
A better way to do this would be:
board = []
for i in range(0, 8):
board.append([])
for j in range(0, 8):
board[i].append((i + j) % 2)
print(board[-1])
Or
def board(k=8):
return [[int(i%2!=j%2) for i in range(k)] for j in range(k)]

Related

DFS solving grid puzzle problem - extremely slow

I borrowed some code from here in order to solve a puzzle game where you must pass over each square on a grid only once and avoid obstacles.
It works fine for anything less than an 8x8 grid but the problem I want to solve is a fairly complex 10x10 grid
Any help would be really appreciated!!! Thank you!
import numpy as np
# Function for dfs.
# i, j ==> Current cell indexes
# vis ==> To mark visited cells
# ans ==> Result
# z ==> Current count 0s visited
# z_count ==> Total 0s present
current_pos = 1
def dfs(i, j, grid, vis, ans, z, z_count):
n = len(grid)
m = len(grid[0])
global grid_test
global current_pos
# Mark the block as visited
vis[i][j] = 1
if ans < 1:
if (grid[i][j] == 0):
# Update the count
z += 1
current_pos += 1
grid_test[i][j] = current_pos
if (z == z_count):
ans += 1
print('worked')
vis[i][j] = 0
return grid, vis, ans
'''if (grid[i][j] == 200):
# If path covered all the non-
# obstacle blocks
if (z == z_count):
ans += 1
vis[i][j] = 0
return grid, vis, ans'''
# Up
if (i >= 1 and not vis[i - 1][j] and
grid[i - 1][j] != -1):
grid, vis, ans = dfs(i - 1, j, grid,
vis, ans, z,
z_count)
# Down
if (i < n - 1 and not vis[i + 1][j] and
grid[i + 1][j] != -1):
grid, vis, ans = dfs(i + 1, j, grid,
vis, ans, z,
z_count)
# Left
if (j >= 1 and not vis[i][j - 1] and
grid[i][j - 1] != -1):
grid, vis, ans = dfs(i, j - 1, grid,
vis, ans, z,
z_count)
# Right
if (j < m - 1 and not vis[i][j + 1] and
grid[i][j + 1] != -1):
grid, vis, ans = dfs(i, j + 1, grid,
vis, ans, z,
z_count)
# Unmark the block (unvisited)
vis[i][j] = 0
current_pos -= 1
return grid, vis, ans
def uniquePaths(grid):
# Total 0s present
z_count = 0
n = len(grid)
m = len(grid[0])
ans = 0
vis = [[0 for j in range(m)]
for i in range(n)]
x = 0
y = 0
for i in range(n):
for j in range(m):
# Count non-obstacle blocks
if grid[i][j] == 0:
z_count += 1
elif (grid[i][j] == 1):
# Starting position
x = i
y = j
grid, vis, ans = dfs(x, y, grid,
vis, ans, 0,
z_count)
print(np.matrix(grid))
print(np.matrix(grid_test))
return ans
The grid that it tries to solve is below, the -1s being the obstacles and the 0s the unvisited grid
# Driver code
if __name__ == '__main__':
grid = [[1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, -1, 0, 0, 0, 0, 0],
[0, 0, -1, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, -1, 0, 0, -1, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
print(uniquePaths(grid))
The output for a simple 8x8 grid like this doesn't take too long
[[ 1 0 0 0 0 0 0 0]
[ 0 0 -1 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 -1 0]
[ 0 0 0 0 0 0 0 0]]
--->>>
Output:
[[ 1 16 17 18 35 36 53 54]
[ 2 15 -1 19 34 37 52 55]
[ 3 14 21 20 33 38 51 56]
[ 4 13 22 31 32 39 50 57]
[ 5 12 23 30 41 40 49 58]
[ 6 11 24 29 42 47 48 59]
[ 7 10 25 28 43 46 -1 60]
[ 8 9 26 27 44 45 62 61]]

Erosion operation (python)

I am trying to implement the erosion function for a binary image without using standard libraries (cv2,..). That's what I got at the moment. Is it possible to simplify my code so that there are only vector or matrix operations? Any other suggestions are also welcome.
mask = np.array([
[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]
])
def erosion(image, mask):
mask_size = mask.shape[0]
left_half = int(mask_size / 2)
right_half = int(mask_size / 2)
if mask_size % 2 == 0:
right_half += 1
result = image.copy()
# Идем по изображению
for i in range(left_half, result.shape[0] - right_half):
for j in range(left_half, result.shape[1] - right_half):
left_border = int(mask_size / 2)
mask_i = 0
mask_j = 0
flag = False
right_border = left_border
if mask_size % 2 != 0:
right_border += 1
# Идем по маске, перебираем каждый элемент маски
for k in range(i - left_border, i + right_border):
mask_j = 0
for l in range(j - left_border, j + right_border):
if mask[mask_i, mask_j] == 1 and image[k, l] == 0:
result[i, j] = 0
flag = True
break
mask_j += 1
mask_i += 1
if(flag):
break
if not (flag):
result[i, j] = 255
return result

how to count negative and positive numbers in each set from a list?

I have list which contains 30 numbers
list = [-21,-22,-33,-55,-454,65,48,-516,614,6,2,-64,-64,-87,6,45,87,15,11,03,-34,-6,-68,-959,-653,24,658,68,9,-2181]
Now first I want to count the number of continuous 3 positive or negative numbers. For that I am using this program:
list = [-21,-22,-33,-55,-454,65,48,-516,614,6,2,-64,-64,-87,6,45,87,15,11,03,-34,-6,-68,-959,-653,24,658,68,9,-2181]
counts = []
count = 0
daysCounter = 1
plus_counter = 0
minus_counter = 0
row_counter = 0
answer_counter = 1
for each in list: # for the "dev column"
if each > 0:
minus_counter = 0
plus_counter += 1
if plus_counter == 3:
count = answer_counter
row_counter = answer_counter
counts.append(count)
plus_counter = 0
answer_counter += 1
else:
counts.append(0)
elif each < 0:
plus_counter = 0
minus_counter += 1
if minus_counter == 3:
count = answer_counter
row_counter = answer_counter
counts.append(count)
minus_counter = 0
answer_counter += 1
else:
counts.append(0)
row_counter += 1
print counts
output:
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3, 0, 0, 4, 0, 0, 5, 0, 0, 6, 0, 0, 0, 0, 7, 0, 0]
This is correct but I want to reset the counter at %10 == 0position. Basically, if the list contains 30 elements then I want to count between 0 to 10th element then 11th to 20th then 21th to 30th element.
desired output:
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0]
Basically, you will have to reset to default values for each period:
# other code
for i, each in enumerate(list): # for the "dev column"
if i % 10 == 0:
count = 0
daysCounter = 1
plus_counter = 0
minus_counter = 0
row_counter = 0
answer_counter = 1
# remaining code
Note: You should not name your list as list, because you override the built-in.
Your question didnt make sense to me, you say you want to reset on every module 10 index, yet you then go on to say in a list of 30 elements you want
0 to 10 (this is 11 elements)
11 to 20 (this is 10 elements)
21 to 30 (this is 10 elements)
The total of this would be 31 elements but you said your list has 30 elements. which would be indexed from 0 to 29. So i have made an assumption here that you do mean every 10 elelemts I.E 0 to 9, 10 to 19, 20 to 29. This makes my output out of line with yours but again i can only make an assumption here that you miscounted with your indexes.
nums = [
-21, -22, -33, -55, -454, 65, 48, -516, 614, 6,
2, -64, -64, -87, 6, 45, 87, 15, 11, 3,
-34, -6, -68, -959, -653, 24, 658, 68, 9, -2181
]
nths = 10
sequential_limit = 3
sequential_count = sequential_finds = 0
indexer = sequential_limit - 1
sequential_list = [0 for _ in range(indexer)]
skip = 0
for index, num in enumerate(nums[indexer:], indexer):
result = 0
if index % nths == 0:
sequential_count = sequential_finds = 0
skip = indexer
if skip:
skip -= 1
else:
negative = sum(1 for next_num in nums[index - indexer:index + 1] if next_num < 0)
positive = sum(1 for next_num in nums[index - indexer:index + 1] if next_num >= 0)
if sequential_limit in (positive, negative):
sequential_finds += 1
sequential_count = 0
skip = indexer
result = sequential_finds
sequential_list.append(result)
print(sequential_list)
OUTPUT
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0]
I think the above desired output you post is not correct
Add this code in the end, This code will reset between 0th to 9th, 10th to 19,20th to 29 elements of a list.
list_len = len(counts)
total_multiple = int(list_len/10)
for i in range(1, total_multiple):
count = 0
for j in range(10*i, 10*i+10):
if(counts[j] > 0):
counts[j] = count
count += 1
print(counts)
It will modify your list and prints
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0]

How to count specific elements before an element in a list?

We have a list
list = [1, 1, 1, 0, 1, 0, 0, 1]
I am trying find a function that would count the number of 0's before each item and then multiply this number by 3.
def formula(n):
for x in list:
if x == 1:
form = n * 3
return form
#If x is 1, count the number of zeros right before x and multiply this by 3,
For example for the list above, the first element is a 1 and there are no numbers right before it, the program should compute 0 * 3 = 0, for the second item, which is also a 1, the number right before it is also not a zero, the program should also compute 0 * 3 = 0. The 4th element is 0 so the program should ignore, For the 5th element which is a 1, the number right before it is a 0, the programme to compute 1 * 3 = 3, for the 6th element the number right before it is a 1, the system should compute 0 * 3 = 0. The 7th element is a 0, since x is not equal to 1 the program should not do anything. For the last element which is a 1, the last two numbers before it are zeros, the program should compute 2 * 3 = 6
I believe you are looking for a generator, with a simple counter:
def get_values (list):
n = 0
for x in list:
if x == 1:
yield n * 3
n = 0 # reset the counter
elif x == 0:
n += 1 # increment the counter
print(list(get_values([1, 1, 1, 0, 1, 0, 0, 1])))
# [0, 0, 0, 3, 6]
Try this,
def formula(l):
count_zero = 0
result = []
for i in l:
if i == 1:
result.append(3*count_zero)
count_zero = 0
elif i == 0:
count_zero += 1
return result
# Test case
l = [1, 1, 1, 0, 1, 0, 0, 1]
result = formula(l)
print(result)
# [0, 0, 0, 3, 6]
Here is my solution for the problem.
test_list = [1, 1, 1, 0, 1, 0, 0, 1]
def formula(list):
track = []
start = 0
for i,n in enumerate(list):
count_list_chunk = list[start:i]
if count_list_chunk.count(0) > 0 and n != 0:
start = i
if n != 0:
track.append( count_list_chunk.count(0)*3 )
return track
print formula(test_list)
#[ 0, 0, 0, 3, 6]

Unable to increment array elements correctly for "Minesweeper"

I'm starting to learn Python, I just started with a simple example. The question was to count mines near each place in a table. Consider input file below:
4 4
*...
....
.*..
....
3 5
**...
.....
.*...
0 0
The output should be like
Field #1:
*100
2210
1*10
1110
Field #2:
**100
33200
1*100
And my code is:
#!/usr/bin/python
import pprint
fin = open("1.2.in")
fout = open("1.2.out")
while True:
i, j = [int(x) for x in fin.readline().split()]
if(i == 0):
break
arr = []
for k in range(0,i):
line = fin.readline();
arr.append(list(line))
pprint.pprint(arr)
resarr = [[0]*j]*i
for row in range(0,i):
for col in range(0,j):
for rowIndex in range(-1,2):
for colIndex in range(-1,2):
# print row,rowIndex, col,colIndex
if (row + rowIndex < i) and (row + rowIndex >= 0) and ( col + colIndex < j) and (col+colIndex >=0) and (rowIndex != 0 or colIndex != 0):
#pprint.pprint(resarr[row][col])
#if arr[row+rowIndex][col+colIndex] == "*":
#print row,rowIndex, col,colIndex, " ", arr[row+rowIndex][col+colIndex]
#print resarr[row][col]
resarr[row][col] += 1
#pprint.pprint(resarr)
# print col+colIndex
print i,j
pprint.pprint(resarr)
I don't know what's wrong, but when I want to increment resarr, a total column is incremented.
Your problem is
resarr = [[0]*j]*i
This means: Take i references to the same list defined by [0]*j and create a list of those.
The thing you want is:
resarr = [[0]*j for _ in range(i)]
This creates a new list ([0, 0, ...]) i times instead.
See this:
>>> a = [0] * 4
>>> a
[0, 0, 0, 0]
>>> b = [a] * 4
>>> b
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
>>> id(b[0]) # get the "address" of b[0]
42848200
>>> id(b[1]) # b[1] is the same object!
42848200
>>> b[0][0] = 1
>>> b
[[1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0]]

Categories