Currently my code adds bombs through random x and y coordinates on my hidden grid. What would I have to add here in order for the code to add numbers if the grid space is touching a bomb?
def addBombNum(bombs,gSize,hiddenGrid,bCount):
fNum = ""
for i in range(bombs):
randPlace = True
while randPlace:
x = random.randint(0,gSize - 1)
y = random.randint(0,gSize - 1)
if hiddenGrid[y][x] == "[-]": hiddenGrid[y][x] = "\033[90m[*]\033[m" ; randPlace = False
if hiddenGrid[y][x] == "\033[90m[*]\033[m": pass
for i in range(gSize):
for j in range(gSize):
if hiddenGrid[i][j] == "\033[90m[*]\033[m": continue
This is my hiddenGrid if needed.
hiddenGrid = [["[-]" for y in range(gSize)] for x in range(gSize)]
I would personally recomment storing the bomb array as a numerical array and having a way to process it into the output afterwards. However, to answer your question directly, what I would recommend doing is each time you place down a bomb, you increment a counter for every cell adjacent to it.
So, at the top of your function, you could first create a number grid: grid = [[0 for y in range(gSize)] for x in range(gSize)].
Next, each time you add a bomb, increment the counter for each grid space that touches it:
for a in range(y - 1, y + 2):
for b in range(x - 1, x + 2):
if 0 <= a < gSize and 0 <= b < gSize:
grid[a][b] += 1
Finally, at the very end, you can just relay this information from the grid to the output. Thus, after the if hiddenGrid[i][j] == "\033[90m[*]\033[m": continue line (which I assume you added to prevent it from overwriting bombs with numbers), you can add this block:
if grid[i][j] > 0:
hiddenGrid[i][j] = "\033[90m[%d]\033[m" % grid[i][j]
A different way you could do it is just add this block to the very end after the bomb skip check:
count = 0
for a in range(i - 1, i + 2):
for b in range(j - 1, j + 2):
if 0 <= a < gSize and 0 <= b < gSize:
if hiddenGrid[a][b] == "\033[90m[*]\033[m":
count += 1
if count > 0:
hiddenGrid[i][j] = "\033[90m[%d]\033[m" % count
This way, you don't need to have the counter grid and don't need to increment it each time. However, having the grid means if you need to use it for other things later on, you have it around and don't need to recompute it every time.
Here is the program I'm trying to write:
The user gives the properties of some domino pieces, some of which are vertical, and some are horizontal, and they are in n rows and m columns. Suppose we are looking at them from above: a horizontal domino can fall either to the right or to the left, and can only make other horizontal dominoes to fall. and a vertical domino can fall to the up or down and can only cause other vertical dominoes to fall.
first the user will give us the number of rows and columns as 'n m', and in the following n lines of input, the user will give lines each made of m characters, like for example m=5: ||-|- The '|' represents a horizontal and the '-' represents a vertical domino.
Now the program is supposed to determine the minimum number of dominoes which we have to push to make them all to fall.
this is the example presented in the question:
input:
3 3
|||
||-
||-
output:
4
We push the first dominoes in each row and the 2nd one in the third column (from left to right)
So here is my code:
dim = input()
n, m = [int(i) for i in dim.split(' ')]
min_d = 0
vertical = []
for q in range(0, m):
vertical.append(n)
for j in range(0, n):
line = list(input())
# horizontal:
if line[0] == '|':
min_d += 1
for l in range(1, m):
if line[l] == '|':
if line[l-1] == '-':
min_d += 1
# vertical:
if j == 0:
for k in range(0, m):
if line[k] == '-':
min_d += 1
vertical[k] = 0
if j > 0:
for p in range(0, m):
if line[p] == '-':
if vertical[p] != j-1:
min_d += 1
vertical[p] = j
print(min_d)
and it works fine for the above example and some other examples I made up and calculated manually. But when I submit this on the site, I get "WRONG ANSWER!" for all the tests! What is wrong with this?
So it sounds like this is more of a problem to do with finding out what the question is saying rather than the code, which given the assumption that each domino can only know the ones directly next to them and facing the same direction is not particularly difficult. Is it possible that the question is actually more complex, and knocking over a domino between two similar facing domino could allow a path for the dominoes to hit each other?
For instance:
3 3
|-|
Could have output
2
Because, knocking the middle domino over first allows to knock the left domino into the right one.
If you transform your initial "matrix" in a string you can then count the number of occurence of -| to find how many vertical push you need to do.
And then you can do the same on the columns by using the occurences of |-.
Something like:
import re
matrix = (
"|||-"
"||--"
"||--"
)
# Size of matrix
x = 3
y = 4
min_push = 0
# By line
regline = re.compile("-\|")
for i in range(0, x*y, y):
current_line = matrix[i:i+y]
if current_line[0] == "|":
min_push += 1
min_push += len(re.findall(regline, current_line))
# Turn the "matrix" string by 90° so columns become lines
matrix_tmp = [ "" for i in range(y) ]
for i in range(x*y):
matrix_tmp[i%y] += matrix[i]
matrix = "".join(matrix_tmp)
# By column
regline = re.compile("\|-")
for i in range(0, x*y, x):
current_col = matrix[i:i+x]
if current_col[0] == "-":
min_push += 1
min_push += len(re.findall(regline, current_col))
print(min_push)
I am trying to write a Python statement for performing the following task with a table of m rows and n columns.
I have to fill only the top row and bottom row with zeros.
So far I have:
list = []
for i in range(m):
for j in range(n):
I'm not sure what to do next. How can I access just the first and last row? Thank you!
Code based on your provided information :
list = []
for x in range(0, m):
if x == 0 or x == m:
# your code for filling it with zeros
else:
# your code for "Anything can be in other cells"
You can use:
lst = [[0 if i in (0, m-1) else default_val] * n for i in range(m)]
That roughly does the same as:
lst = [] # do not shadow 'list'
for i in range(m):
lst[i] = []
for j in range(n):
lst[i].append(0 if i in (0, m-1) else default_val)
I am a beginner to programming. I always encounter this problem for matrices. Please help me to correct this code and understand the concept behind this. Thank you.
def new_matrix(matrix_size, center_num):
c = matrix_size / 2
if matrix_size % 2 != 0:
p = matrix_size
print("enter a valid size for matrix")
else:
matrix = [[0] * matrix_size for z in range(matrix_size)]
for counting in range(center_num, (matrix_size ** 2) + center_num):
for i in range(2, matrix_size+1):
row = int(c)
column = int(c)
if (i % 2 == 0):
for k in range(1, i + 1): # moving right
column += 1
matrix[column][row] = counting
for k in range(1, i + 1): # moving up
row += 1
matrix[column][row] = counting
else:
for k in range(1, i + 1): # moving left
column -= 1
matrix[column][row] = counting
for k in range(1, i + 1): # moving down
row -= 1
matrix[column][row] = counting
print(matrix)
new_matrix(6, 2)
This issue here seems to be that your indexing is off. The end value in range(n) is n-1, which means that in your for loop when i = matrix_size and then you try to increment the column beyond this, you're trying to assign a value to an index in the matrix that doesn't exist.
You can either try and fix your loop, i.e. reduce it by one, or you can do something like the following,
try:
<your code goes here>
except IndexError:
pass
And then anytime the loop hits an index error it will skip that index and try the next. It's better to fix the code though!
I'm trying to make a python script, that gets me the longest repeated character in a given matrix (horizontally and vertically).
Example:
I have this matrix:
afaaf
rbaca
rlaff
Giving this matrix for input, it should result: a 3
You can see that that the 3rd column of the matrix, is full of a's and also, it's the most repeated character in the matrix.
What I have:
#!/bin/python2.7
#Longest string in matrix
#Given a matrix filled with letters. Find the longest string, containing only the same letter, which can be obtained by starting
#with any position and then moving horizontally and vertically (each cell can be visited no more than 1 time).
# Settings here
# -------------
string_matrix = """
afaaf
rbaca
rlaff
"""
pos = (0,0)
# -------------
import pdb
import time
import collections
from collections import defaultdict
import re
rows = 0
columns = 0
matrix = []
matrix2 = []
counter = 0
res_l = []
i = 0
c = ''
# if matrix2 is full of 1's, stop
def stop():
for i in range(0, rows):
for j in range(0, columns):
if matrix2[i][j] == 0:
return False
return True
# checks the points, and returns the most repeated char and length
def check_points(points1, points2):
r = []
r.append(-1)
r.append('')
# create strings from matrix
s1 = ''
s2 = ''
for point in points1:
s1 += matrix[point[0]][point[1]]
for point in points2:
s2 += matrix[point[0]][point[1]]
rr = {}
for c in s1:
rr[c] = 0
for c in s2:
rr[c] = 0
for i in range(0, len(s1)):
k = 1
for j in range(i+1, len(s1)):
if s1[i] == s1[j]:
k += 1
else:
break
if k > rr[s1[i]]:
rr[s1[i]] = k
for i in range(0, len(s2)):
k = 1
for j in range(i+1, len(s2)):
if s2[i] == s2[j]:
k += 1
else:
break
if k > rr[s2[i]]:
rr[s2[i]] = k
m = -1
c = ''
for key,value in rr.iteritems():
if value > m:
m = value
c = key
return m, c
# Depth-first search, recursive
def search(pos):
global res_l
global matrix2
global c
counter = 0
x = pos[0]
y = pos[1]
c = matrix[x][y]
# base clause
# when matrix2 is all checked
if stop():
return counter, c
points1 = []
points2 = []
allpoints = []
for i in range(0, columns):
if matrix2[x][i] != 1:
points1.append([x, i])
allpoints.append([x, i])
for i in range(0, rows):
if matrix2[i][x] != 1:
points2.append([i, x])
allpoints.append([i, x])
r = check_points(points1, points2)
if r[0] > counter:
counter = r[0]
c = r[1]
matrix2[x][y] = 1
for point in allpoints:
rr = search(point)
if rr[0] > counter:
counter = int(rr[0])
c = rr[1]
#print 'c: ' + str(c) + ' - k: ' + str(counter)
return counter, c
def main():
# create the matrix from string
string_matrix_l = string_matrix.strip()
splited = string_matrix_l.split('\n')
global rows
global columns
global matrix
global matrix2
rows = len(splited)
columns = len(splited[1])
# initialize matrixes with 0
matrix = [[0 for x in range(columns)] for x in range(rows)]
matrix2 = [[0 for x in range(columns)] for x in range(rows)]
# string to matrix
i = 0
for s in splited:
s = s.strip()
if s == '':
continue
j = 0
for c in s:
try:## Heading ##
matrix[i][j] = c
#print 'ok: ' + str(i) + ' ' + str(j) + ' ' + c
except:
print 'fail: index out of range matrix[' + str(i) + '][' + str(j)+'] ' + c
j = j + 1
i = i + 1
# print some info
print 'Given matrix: ' + str(matrix) + '\n'
print 'Start position: ' + str(pos)
print 'Start character: ' + str(matrix[pos[0]][pos[1]])
# get the result
res = search(pos)
print '-------------------------------------'
print '\nChar: ' + str(res[1]) + '\nLength: ' + str(res[0])
if __name__ == "__main__":
main()
This is my source code.
The example given above, is also used in the source code. The result given is: r 2 which is wrong ... again, should be a 3
It has 4 functions: main, search, stop and check_points.
main is initializing things up,
search is my recursive function that takes one parameter (the start point), and should recursively check for the longest string. I have another matrix, same length as original, which is just 1 and 0. 1 means the position was visited, 0, not. The search function is setting 1 on the right position after a certain position was processed by the search function.
stop is checking if matrix2 is full of 1's, in this case, the matrix was all parsed
check_points takes 2 parameters, 2 list of points, and returns the most repeated character and it's length for those points
What doesn't work:
Most of the time is giving me the wrong character as result, even thought the count might be right sometimes. Sometimes it's working on horizontally, sometimes it doesn't. I am sure that I'm doing something wrong, but ... it's over 1 week now since I'm trying to figure out how to do this. Asked another question here on stackoverflow, got bit further but ... still stuck.
Any suggestion is appreciated.
You can use itertools.groupby to quickly find the count of repetitions of some character, and izip_longest(*matrix) to transpose the matrix (swap its rows and columns).
from itertools import groupby, izip_longest
matrix_string = """
afaaf
rbaca
rlaff
"""
def longest_repetition(row):
return max((sum(1 for item in group), letter)
for letter, group in groupby(row)
if letter is not None)
def main():
matrix = [[letter for letter in row.strip()]
for row in matrix_string.strip().split('\n')]
count, letter = max(
max(longest_repetition(row) for row in matrix),
max(longest_repetition(col) for col in izip_longest(*matrix))
)
print letter, count
if __name__ == '__main__':
main()
Since you've updated the requirement here is a recursive version of the code with some explanations. If it were not an assignment and this task came up in some real life problem, you should really have used the first version.
matrix_string = """
afaaf
rbaca
rlaff
"""
def find_longest_repetition(matrix):
rows = len(matrix)
cols = len(matrix[0])
# row, col - row and column of the current character.
# direction - 'h' if we are searching for repetitions in horizontal direction (i.e., in a row).
# 'v' if we are searching in vertical direction.
# result - (count, letter) of the longest repetition we have seen by now.
# This order allows to compare results directly and use `max` to get the better one
# current - (count, letter) of the repetition we have seen just before the current character.
def recurse(row, col, direction, result, current=(0, None)):
# Check if we need to start a new row, new column,
# new direction, or finish the recursion.
if direction == 'h': # If we are moving horizontally
if row >= rows: # ... and finished all rows
return recurse( # restart from the (0, 0) position in vertical direction.
0, 0,
'v',
result
)
if col >= cols: # ... and finished all columns in the current row
return recurse( # start the next row.
row + 1, 0,
direction,
result
)
else: # If we are moving vertically
if col >= cols: # ... and finished all columns
return result # then we have analysed all possible repetitions.
if row >= rows: # ... and finished all rows in the current column
return recurse( # start the next column.
0, col + 1,
direction,
result
)
# Figure out where to go next in the current direction
d_row, d_col = (0, 1) if direction == 'h' else (1, 0)
# Try to add current character to the current repetition
count, letter = current
if matrix[row][col] == letter:
updated_current = count + 1, letter
else:
updated_current = 1, matrix[row][col]
# Go on with the next character in the current direction
return recurse(
row + d_row,
col + d_col,
direction,
max(updated_current, result), # Update the result, if necessary
updated_current
)
return recurse(0, 0, 'h', (0, None))
def main():
matrix = [[letter for letter in row.strip()]
for row in matrix_string.strip().split('\n')]
count, letter = find_longest_repetition(matrix)
print letter, count
if __name__ == '__main__':
main()
You can also try the collections.Counter(string).most_common() to get the most repetitions of a character.
from collections import Counter
string_matrix = """
afaaf
rbaca
rlaff
"""
def GetMostRepetitions(pos):
mc = []
for ii in range(pos[0],len(working_mat)):
mc.extend(Counter(working_mat[ii]).most_common(1))
for jj in range(pos[1],len(working_mat[0])):
column = []
for kk in range(ii,len(working_mat)):
column.append(working_mat[kk][jj])
mc.extend(Counter(column).most_common(1))
m = 0
for item in mc:
if item[1] > m:
m = item[1]
k = item[0]
print(k, m)
working_mat = string_matrix.strip().split('\n')
for ii in range(len(working_mat)):
for jj in range(len(working_mat[0])):
pos = (ii,jj)
GetMostRepetitions(pos)
As Kolmar said, you can also use a better way to transpose the matrix.