I have a function that draws rectangles:
def drawTbl(l, w):
ln1 = ' '
ln2 = '-'
ln3 = '|'
x = range(l)
print '+', ln2*w, '+'
for i in range(len(x)):
print ln3, ln1*w, ln3
print '+', ln2*w, '+'
It works fine, but I'm attempting to kind of graph this (this is like a pong clone) so that I can place a ball 'O' at the center and use X and Y for collision detection. When I use this function:
def tblData(l, w):
table=[]
for x in range(l):
table.append([])
for y in range(w):
table.append([])
It does seem to append the blank lists, but when I try to use table[x][y], all I receive is an error.
When I return table from tblData, I do get a list of empty lists,
but say (l, w) is (12, 56), so I'm trying to place ball 'O' at the center of the grid (6, 28), simply typing table[6][28] returns an error, so I don't know how I would append 'O' to table[6,28]
So my question is, how can I effectively access list[x][y]?
Instead of creating empty lists you will need to initialize the values in the inner lists to some reasonable value, like a space.
For example:
def tblData(l, w):
table=[]
for x in range(l):
table.append([' '] * w)
return table
Or more concisely:
def tblData(l, w):
return [[' '] * w for x in range(l)]
Note that [' '] * 3 creates the list [' ', ' ', ' '], so [' '] * w is equivalent to
[' ' for x in range(w)].
For example:
>>> import pprint
>>> table = [[' '] * 4 for x in range(5)]
>>> pprint.pprint(table)
[[' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ']]
>>> table[3][1] = 'O'
>>> pprint.pprint(table)
[[' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' '],
[' ', 'O', ' ', ' '],
[' ', ' ', ' ', ' ']]
Related
I am attempting to code a FEN number calculator based on a board:
boardPeices = ['br', 'bn', 'bb', 'bq', 'bk', 'bb', 'bn', 'br',
'bp', 'bp', 'bp', 'bp', 'bp','bp', 'bp', 'bp',
' ', ' ', ' ', ' ', ' ',' ', ' ', ' ',
' ', ' ', ' ', ' ', ' ',' ', ' ', ' ',
' ', ' ', ' ', ' ', ' ',' ', ' ', ' ',
' ', ' ', ' ', ' ', ' ',' ', ' ', ' ',
'wp', 'wp', 'wp', 'wp', 'wp','wp', 'wp', 'wp',
'wr', 'wn', 'wb', 'wq', 'wk','wb', 'wn', 'wr',
]
and have gotten pretty far, to where I have 8 stings, each with a row of the FEN number. Currently, the below code prints this: rnbqkbnr/pppppppp/11111111/11111111/11111111/11111111/PPPPPPPP/RNBQKBNR
print(f'{fenRow1}/{fenRow2}/{fenRow3}/{fenRow4}/{fenRow5}/{fenRow6}/{fenRow7}/{fenRow8}')
The problem is, the FEN number's ones should be concentrated into 8's, as there are 8 numbers next to each other. Due to everything being in strings, I cannot figure out how to add the 8 numbers together, in a way that a different position would still work, where the numbers are separated (ie, after e4)
You can use itertools.groupby:
from itertools import groupby
s = 'rnbqkbnr/pppppppp/11111111/11111111/11111111/11111111/PPPPPPPP/RNBQKBNR'
out = ''.join([x for k, g in groupby(s, lambda x: x=='1')
for x in ([str(len(list(g)))] if k else list(g))])
Output:
'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR'
Example on another input (s = 'rnbqkbnr/ppp1pppp/111p1111/11111111/11111111/11111111/PPPPPPPP/RNBQKBNR'):
'rnbqkbnr/ppp1pppp/3p4/8/8/8/PPPPPPPP/RNBQKBNR'
Use short regex substitution:
import re
s = 'rnbqkbnr/pppppppp/11111111/11111111/11111111/11111111/PPPPPPPP/RNBQKBNR'
new_s = re.sub(r'\d{2,}', lambda m: str(len(m.group())), s)
rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR
I have a variable, representing a chessboard filled with random chess pieces. The variable consists of a list of 8 lists,each containing 8 positions filled with either " " (empty position) or a specific chess piece (e.g. "♞"):
chessboard = [
[' ',' ',' ',' ',' ',' ',' ',' '],
[' ',' ',' ',' ',' ',' ',' ',' '],
[' ',' ',' ',' ',' ','♞','♞',' '],
[' ',' ',' ',' ',' ',' ',' ',' '],
[' ',' ',' ',' ',' ',' ',' ',' '],
[' ',' ','♔',' ',' ',' ',' ',' '],
[' ',' ',' ',' ',' ',' ',' ',' '],
[' ',' ',' ',' ',' ',' ',' ',' ']
]
I would like to collect the information of each individual piece in a list:
pieces = []
for row in chessboard:
for piece in row:
if piece != " ":
pieces.append((piece, row.index(piece), chessboard.index(row)))
The above for loop ALMOST works. It has one problem. If there are multiple identical pieces in the same row, it adds the coordinates of the first iterated piece:
[('♞', 5, 2), ('♞', 5, 2), ('♔', 2, 5)]
The second knight should be in position 6,2. Can anybody suggest a workaround?
Using a list comprehension:
out = [(item, j, i) for i,row in enumerate(chessboard)
for j,item in enumerate(row) if item != ' ']
or numpy.where:
import numpy as np
a = np.array(chessboard)
i,j = np.where(a!=' ')
out = list(zip(a[i,j], j, i))
output:
[('♞', 5, 2), ('♞', 6, 2), ('♔', 2, 5)]
enumerate the rows and columns.
pieces = []
for i, row in enumerate(chessboard):
for j, piece in enumerate(row):
if piece != " ":
pieces.append((piece, i, j))
Loop over enumerate(row) and enumerate(row), and if the cell isn't ' ' then add the indices to your list. This is also more efficient, as your solution loops across each row multiple times - once to get across the row, and once each time it wants to find the index of a piece.
There are already some good answers to this question, but I find that numpy may be a good choice for this question:
>>> import numpy as np
>>> board = np.array(chessboard)
>>> board
array([[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', '♞', '♞', ' ', ' '],
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
[' ', ' ', '♔', ' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']], dtype='<U1')
>>> i, j = (board != ' ').nonzero()
>>> list(zip(board[i, j], j, i))
[('♞', 4, 2), ('♞', 5, 2), ('♔', 2, 5)]
I'm Trying to make a more advanced Tic Tac Toe program with an 'infinite' amount of lines/rows.
But when I try to mutate the list, it changes the whole column instead of just one spot.
size = 4
board = size * [size*[' ']]
board[0][1] = 'x'
#output:
#[[' ', 'x', ' ', ' '],
# [' ', 'x', ' ', ' '],
# [' ', 'x', ' ', ' '],
# [' ', 'x', ' ', ' ']]
How can I fix that?
It occurs because the inner list each row is made of is the same object that gets repeated.
You can change it to
board = [
[' ']*size
for _ in range(size)
]
Or use a double list comprehension
size = 4
board = [
[' ' for _ in range(size)]
for _ in range(size)
]
board[0][1] = 'x'
print(board)
which both produce
[[' ', 'x', ' ', ' '], [' ', ' ', ' ', ' '], [' ', ' ', ' ', ' '], [' ', ' ', ' ', ' ']]
Kudos to #Pynchia for beating me to the answer. Here is my version of code. I think the problem you were having was a result of your method of creating a list of lists.
size = 4
# simple way to create a list of lists
board = [size * [' '] for i in range(4)]
board[0][1] = 'x'
print(board)
Output will be as expected.
So I was trying to write a function called find_treasure which takes a 2D list as a parameter. The purpose of the function is to search through the 2D list given and to return the index of where the 'x' is located.
def find_treasure(my_list):
str1 = 'x'
if str1 in [j for i in (my_list) for j in i]:
index = (j for i in my_list for j in i).index(str1)
return(index)
treasure_map = [[' ', ' ', ' '], [' ', 'x', ' '], [' ', ' ', ' ']]
print(find_treasure(treasure_map))
However, I can't seem to get the function to return the index, I tried using the enumerate function too but either I was using it wrongly.
Using enumerate
def find_treasure(my_list):
str1 = 'x'
for i,n in enumerate(my_list):
for j, m in enumerate(n):
if m == str1:
return (i, j)
treasure_map = [[' ', ' ', ' '], [' ', 'x', ' '], [' ', ' ', ' ']]
print(find_treasure(treasure_map))
Output:
(1, 1)
Using index function.
def find_treasure(my_list):
str1 = 'x'
for i,n in enumerate(my_list):
try:
return (i, n.index(str1))
except ValueError:
pass
treasure_map = [[' ', ' ', ' '], [' ', 'x', ' '], [' ', ' ', ' ']]
print(find_treasure(treasure_map))
Output
(1, 1)
Is there a way to count the amount occurrences of a set of string lists?
For example, when I have this list, it counts 7 ' ' blanks.
list = [[' ', ' ', ' ', ' ', ' ', ' ', ' ']]
print(list.count(' '))
Is there a way I can do this same thing but for a set of multiple lists? Like this for example below:
set = [[' ', ' ', ' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' ', ' ', ' ']]
print(set.count(' '))
When I do it this same way, the output I get is 0 and not the actual count of occurrences.
Solution
This works:
>>> data = [[' ', ' ', ' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' ', ' ', ' ']]
>>> sum(x.count(' ') for x in data)
21
You need to count in each sub list. I use a generator expression to do this and sum the results from all sub lists.
BTW, don't use set as a variable name. It is a built-in.
Performance
While not that important for many cases, performance can be interesting:
%timeit sum(x.count(' ') for x in data)
1000000 loops, best of 3: 1.28 µs per loop
vs.
%timeit sum(1 for i in chain.from_iterable(data) if i==' ')
100000 loops, best of 3: 4.79 µs per loop