falling dominoes, debugging - python

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)

Related

All the possible states for wild tic tac toe (wild Tic-tac-toe combinatorics)

Wild tic-tac-toe is an impartial game similar to tic-tac-toe. However, in this game players can choose to place either X or O on each move
what are all the possible states after the change in that rule? and how can I generate all the valid states using python?
that is my try to solve the question, But it is the wrong way
this is the wrong solution
There are only 3**9, or 19,683 possible combinations of placing x, o, or in the grid, and not all of those are valid.
First, a valid game position in the classic tic tac toe is one where the difference between x and o counts is no more than one since they have to alternate moves, but this is not the case here.
In addition, it's impossible to have a state where both sides have three in a row, so they can be discounted as well. If both have three in a row, then one of them would have won in the previous move.
There's actually another limitation in that it's impossible for one letter X or O to have won in two different ways without a common cell (again, they would have won in a previous move), meaning that:
XXX
OOO
XXX
cannot be achieved, while:
XXX
OOX
OOX
make sense.
so I thought the invalid states are the states where we have two winning lines in the same direction(vertically or horizontally)
here is the code:
import numpy as np
def checkRows(board):
i = -1
for row in board:
i += 1
if len(set(row)) == 1 and set(row) != {''}:
r = row[0]
board[i][0] = board[i][1] = board[i][2] = ''
return r
return 0
def checkinvalide(board):
for newBoard in [board, np.transpose(board)]:
k = 0
result = checkRows(newBoard)
if result:
k += 1
result = checkRows(newBoard)
if result:
k += 1
if k == 2:
return k
return k
def generatelists():
StatesMatrix = np.zeros((3**9,9))
for i in range(3**9):
c = i
for j in range(9):
StatesMatrix[i][j] = c % 3
c //= 3
dic = {}
for i in StatesMatrix:
e += 1
i = ["X" if item == 1 else item for item in i]
i = ["O" if item == 2 else item for item in i]
i = ["" if item == 0 else item for item in i]
dd_board = np.reshape(i, (3, 3))
result = checkinvalide(dd_board)
if result != 2:
dic.update({tuple(i): 0})
k += 1
print(k)
return dic
generatelists()
doing the code generates 19177 states
this is wrong solution, there are states where there are two winning lines not in the same direction
The state XXX, _X_, X_X has three winning lines, and no two of them are parallel
You could apply this logic to determine if a board is valid or not:
If there are multiple three-in-a-rows for a certain symbol, make sure they all overlap at the same cell.
I would represent the board state as an integer: each pair of bits represent a cell. The pair can be 0b00 (empty), 0b01 ("X") or 0b10 ("O"). A board has 9 cells, so 18 bits.
Then I would not generate all states, but perform a depth-first traversal in states by adding a symbol at each recursion level. Once a board is invalid, we can backtrack and so skip a lot of invalid states.
Here is an implementation:
patterns = (
(0x0003F, 0x00015), # Horizontal
(0x00FC0, 0x00540),
(0x3F000, 0x15000),
(0x030C3, 0x01041), # Vertical
(0x0C30C, 0x04104),
(0x30C30, 0x10410),
(0x30303, 0x10101), # Diagonal
(0x03330, 0x01110)
)
def valid(board, side):
found = 0x3FFFF
for mask, three in patterns:
if board & mask == three << side:
found &= three
if not found: # Parallel or overlapping at different cells
return False
return True
def countstates(board=0, side=0, i=0):
if not valid(board, side):
return 0
# Iterate all next cells, and for each, the two possible moves (bits)
# There are 9 cells, so 18 bits:
return 1 + sum(
countstates(board | (1 << j), j % 2, j + 2 - j % 2)
for j in range(i, 18)
)
print(countstates()) # 19035
To make it easier to test a few boards, I used the following code:
def statefromstring(s):
board = 0
for ch in s.replace(" ", ""):
board = board * 4 + ".XO".index(ch)
return board
print(valid(statefromstring("XXX .X. X.X"), 0)) # False

Appearing animation for spiral matrix

I'm trying to make a spiral matrix, but when I tried to make the numbers appear one by one, it only shows the lines one by one.
Please help!
import numpy as np
from time import sleep
n = int(input("Width : "))
k = int(input("Space : "))
a = np.zeros((n,n))
print(a/n)
i = 0 #i line
j = 0 #j column
it = -1 #it upper line
id = n #id downer line
jt = -1 #jt left column
jp = n #jp right column
x = k #x starter number
while j < jp:
while j < jp:
a[i][j] = x
x += k
j +=1
it +=1
i=it+1
j=jp-1
while i< id:
a[i][j] = x
x += k
i +=1
jp -=1
j=jp-1
i=id-1
while j > jt:
a[i][j] = x
x += k
j -=1
id -=1
i=id-1
j=jt+1
while i>it:
a[i][j] = x
x += k
i -=1
jt +=1
i=it+1
j=jt+1
for x in a:
print(x)
sleep(0.1)
Here's an example:
Each number is suppose to appear one by one.
(I'm just putting this here so I can post this since I need to add more details)
Not quite trivial.
I found a solution using an empty character array and cursor-manipulation.
This should result in the desired output:
# replace your last "for x in a" loop by the following
def print_array(arr, block_size=4):
"""
prints a 2-D numpy array in a nicer format
"""
for a in arr:
for elem in a:
print(elem.rjust(block_size), end="")
print(end="\n")
# empty matrix which gets filled with rising numbers
matrix_to_be_filled = np.chararray(a.shape, itemsize=3, unicode=True)
for _ in range(a.size):
# find position of minimum
row, col = np.unravel_index(a.argmin(), a.shape)
# add minimum at correct position
matrix_to_be_filled[row, col] = f'{a.min():.0f}'
# write partially filled matrix
print_array(matrix_to_be_filled)
# delete old minimum in a-matrix
a[row, col] = a.max()+1
sleep(0.1)
# bring cursor back up except for last element
if _ < a.size-1:
print('\033[F'*(matrix_to_be_filled.shape[0]+1))
If you are using pycharm, you need to edit the run/debug configuration and active "emulate terminal in output console" to make the special "move up" character work

I am looking for a way to make my Minesweeper game add numbers around the bombs

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.

Don't work calculation for matrix 1xm and nx1 in Python (Not NumPy)

I am new in Python. I have got such task:
Write a program that receives a rectangular matrix as a sequence of
rows as its input. The last line of the matrix is followed by a line
containing only the string "end".
The program should output a matrix of the same size, in which each
element at position i, j is equal to the sum of the elements of the
first matrix at positions (i-1, j), (i + 1, j), (i, j-1), (i , j + 1).
For extreme characters, the adjacent element is on the opposite side
of the matrix.
In the case of one row / column, the element itself is a neighbor in
the corresponding direction.
For example
Sample Input 1:
9 5 3
0 7 -1
-5 2 9
end
Sample Output 1:
3 21 22
10 6 19
20 16 -1
I wrote code that work for rectangle and square matrices, but I do not know how to make it work on matrix 1 x m and n x 1.
l2 = []
l3 = []
length = 0
width = 0
while True:
x = input()
if x == 'end':
break
else:
length = 0
for i in x:
if i.isdigit():
length+=1
l2.append(x)
width+=1
for i in l2:
l3.append(i.split(" "))
converted = [[int(i) for i in s] for s in l3]
for i in range(0,width):
for j in range(0,length):
if j==length-1:
j = -1
if i==width-1:
i = -1
print((converted[i-1][j]+converted[i][j-1])+(converted[i][j+1]+converted[i+1][j]), end = " ")
print(end = "\n")
Also I can't use any classes, functions or libraries.
Somebody know how I can fix it ?
P.S. If someone will offer short code, I will be very grateful.
Yes, you need to handle both edges. You're not quite doing that. In particular, when width is 1, you'll set j = -1, and then you try to use j-1, which is out of range.
l2 = []
while True:
x = input()
if x == 'end':
break
l2.append( [int(k) for k in x.split()] )
width = len(l2)
length = len(l2[0])
converted = l2
for i in range(width):
for j in range(length):
im1 = (i-1)%width
ip1 = (i+1)%width
jm1 = (j-1)%length
jp1 = (j+1)%length
print((converted[im1][j]+converted[i][jm1])+(converted[i][jp1]+converted[ip1][j]), end = " ")
print()

Count battleship leetcode that doesn't output the same value after changing parameters

Prompt:
Given an 2D board, count how many battleships are in it. The battleships are represented with 'X's, empty slots are represented with '.'s. You may assume the following rules:
You receive a valid board, made of only battleships or empty slots.
Battleships can only be placed horizontally or vertically. In other words, they can only be made of the shape 1xN (1 row, N columns) or Nx1 (N rows, 1 column), where N can be of any size.
At least one horizontal or vertical cell separates between two battleships - there are no adjacent battleships.
Example:
count_bs([["X",".",".","X"],[".",".",".","X"],[".",".",".","X"]])
returns 2
[X, ., ., X]
[., ., ., X]
[., ., ., X]
Solution: This code is correct.
def count_bs(grid):
rows, cols = len(grid), len(grid[0])
count = 0
for r in range(rows):
for c in range(cols):
if ((grid[r][c] == '.') or (r > 0 and grid[r-1][c] == 'X') or (c > 0 and grid[r][c-1]) == 'X'):
continue
else:
count += 1
return count
I was messing around with the 2D array and changed the parameters to see if it's correct. range(x-1) and in the conditions (r < len(grid) and grid[checks below instead of above) However, I do not get the same answer. How are these two not identical?
def count_bs(grid):
rows, cols = len(grid), len(grid[0])
count = 0
for r in range(rows-1):
for c in range(cols-1):
if ((grid[r][c] == '.') or (r < rows and grid[r+1][c] == 'X') or (c < cols and grid[r][c+1]) == 'X'):
continue
else:
count += 1
return count
So, the code above goes from top left to bottom right and checks the rows above and columns to the left to see if there are adjacent 'X' values. My code also goes from top left to bottom right, but checks the rows to the bottom and right.
Only a few small changes are needed to make your code work. You still need to loop over the entire range of rows and cols, but since you're looking at cells below and to the right of your current position, you need to change the conditions inside the loop. See here:
def count_bs(grid):
rows, cols = len(grid), len(grid[0])
count = 0
for r in range(rows):
for c in range(cols):
if ((grid[r][c] == '.')
or (r < rows-1 and grid[r+1][c] == 'X')
or (c < cols-1 and grid[r][c+1] == 'X')):
continue
else:
count += 1
return count
I only tried a few test cases but I believe this will work. As a side note, the original solution you gave is essentially counting the number of "top-left" corners of the ships, whereas your solution is counting the number of "bottom-right" corners (i.e., if we're at an X and there is not an X below us or to the right, then we must be at a bottom-right corner, so we increment the count). This might make the code a little more intuitive.

Categories