Moving object in list - python

I made a list like this:
mapxy = [[0 for x in range(16)] for x in range(16)]
and I add object from another normal list like this:
for y in range(0, 16):
for x in range(0, 16):
mapxy[x][y] = mapList[o]
Then I want to move one object in the list both down and just change the first index moving it left and right in the list mapxy[x+1][y]
mapxy.pop(f_pos_x)
mapxy.insert(f_pos_x + 1, ["1"])
f_pos_x += 1
(this didn't work quite as I wanted it too, it ended up in-between/created another list inside the first list instead of inserting in the inner list like I wanted it to.)
but also up and down on y: mapxy[x][y+1].
How I want it to look:
Original
mapxy = [[" ", " ", "1"," "][" ", " ", " "," "][" ", " ", " "," "][" ", " ", " "," "]]
When i press right:
mapxy = [[" ", " ", " ","1"][" ", " ", " "," "][" ", " ", " "," "][" ", " ", " "," "]]
And when I press down:
mapxy = [[" ", " ", " "," "][" ", " ", " ","1"][" ", " ", " "," "][" ", " ", " "," "]]

mapxy is a list of lists (with apparently all "cells" initialized to the single item mapList[o], which is slightly strange). So pop and insert into it would remove and respectively add a whole list at a time, not a single item.
You say you want to "move" an item but not what should take its place. If you just want to copy the item, it's clearly just:
map[x+1][y] = map[x][y]
but if the previous map[x][y] must be filled w/something else you'll then have to assign to that, too, of course. Exactly the same for "moving" along y rather than along x.

Use a dictionary with a tuple as key:
map = {}
for x in range(16):
for y in range(16):
map[x, y] = 0
Actually, you could avoid the initialization and check whether an element is set or use a default value. Concerning this default value, consider None, too. With this dict, you can "move" elements easily:
map[1, 2] = 42
v = map.pop((1, 2))
map[3, 4] = v

Here is the full script that I think does what you want. But before I just paste it and run away, there two things worth saying. 1. You need to swap items in-place. 2. You need to cater for the out of range index errors.
To first i envisaged using a deque of deques with maxlen field set. deque is available from the collections library. So to shift left, you pop at the right and insert at the left and to shift to the right you pop at the left and append at the right. But then I had another idea.
You stick with the list of lists, you swap items in-place and avoid out of range errors by the new computed index is within the set of non-negative integers modulo length of the list containing the item.
Enough talking. To swap in-place in python, given:
x = [8, 21, 100, 9, 5]
You do:
x[2], x[3] = x[3], x[2]
Resulting in:
x = [8, 21, 9, 100, 5]
The script below keeps track of two indices, x corresponds to the index of the item, the string, being moved left and right and y corresponds to the index of the inner list item containing the the item to be moved left and right (the inner list itself is moved up and down). By index i mean position. So x points to the string, y points to the list.
To move up and down the containing list, you only need to know the index of the list to move, y. To move left and right the item (the string), you need to know both the containing list index y and the item index x.
#!/usr/bin/python
from collections import deque
def move_dowm(data, y):
old_y = y
y = (y + 1) % len(data)
data[old_y], data[y] = data[y], data[old_y]
return y
def move_up(data, y):
old_y = y
y = (y - 1) % len(data)
data[old_y], data[y] = data[y], data[old_y]
return y
def move_right(data, x, y):
old_x = x
x = (x + 1) % len(data[y])
data[y][old_x], data[y][x] = data[y][x], data[y][old_x]
return x
def move_left(data, x, y):
old_x = x
x = (x - 1) % len(data[y])
data[y][old_x], data[y][x] = data[y][x], data[y][old_x]
return x
if __name__ == '__main__':
dataset = [
[' ', ' ', ' ', ' '],
['1', ' ', ' ', ' '],
[' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' '],
]
x, y = 0, 1
print dataset
print '-' * 90
y = move_up(dataset, y)
print dataset
print '-' * 90
y = move_dowm(dataset, y)
print dataset
print '-' * 90
x = move_left(dataset, x, y)
print dataset
print '-' * 90
x = move_right(dataset, x, y)
print dataset
print

Related

How to make the two different code outputs appear in the same area?

I am trying to merge two outputs together so that it appears something like this:
0 1 2
0 ? ? ?
1 ? ? ?
2 ? ? ?
But it ended up appearing like this instead:
0 1 2
0
1
? ? ?
? ? ?
I tried this to make the codes appear but i have no idea how to place their outputs together
import random
rows = [3]
columns = [4]
def rowscol():
for j in range(columns[0]):
print(" " * 1, end="")
print(j, end="")
print()
for i in range(rows[0]):
print(i)
rowscol()
def create_game_board(rows, columns):
board = [[random.choice("ABCDEFGHIJKLMNOPQRSTUVWXYZ") for _ in range(columns[0])] for _ in range(rows[0])]
# If number of cells is odd, make the last cell an unused cell
if (rows[0] * columns[0]) % 2 != 0:
board[-1][-1] = "#"
return board
board = create_game_board(rows,columns)
# Function to display the game board
def display_board(board):
pad = " " * 30
for row in board:
line = pad + " ".join('?' if column != '#' else '#' for column in row)
print(line)
display_board(board)
Welcome to StackOverflow!
When using multidimensional arrays, like in your case a list of lists, I like to be able to index into them easily. Because of this I usually change it to a dict and use the coordiantes as keys. This way you can even store additional information about the board, like the dimension sizes or anything else.
I added a bunch of comments to explain how the code works but feel free to ask if anything isn't clear:
import random
import string
def create_game_board(rows, cols):
board = dict()
# save dimensions inside the dict itself
board['cols'] = cols
board['rows'] = rows
for y in range(rows):
for x in range(cols):
# add random letter to board at (x,y)
# x,y makes a tuple which can be a key in a dict
# changed to use string.ascii_uppercase so that you don't forget any letter
board[x, y] = random.choice(string.ascii_uppercase)
# change last element to # when both dimensions are odd
if (rows * cols) % 2 == 1:
board[rows-1, cols-1] = "#"
return board
def display_board(board):
# get dimensions
cols, rows = board['cols'], board['rows']
# print header
print(' '.join([' '] + [str(x) for x in range(cols)]))
for y in range(rows):
# print rows
#print(' '.join([str(y)] + [board[x, y] for x in range(cols)])) # to display the actual letter at this location
print(' '.join([str(y)] + ['?' if board[x, y] == '#' else '#' for x in range(cols)])) # using your display function
print() # separator empty line
board = create_game_board(3, 3)
display_board(board)
The output is nothing special when I'm using your method of printing, you might need to change that, I'm not sure how you wanted to display it. I added a line that allows you to print the values on those coordinates.
This is the output:
0 1 2
0 # # #
1 # # #
2 # # ?
Maybe something like?
def draw_board(board):
print(" " + " ".join([str(i) for i in range(len(board[0]))])) # print column numbers
for i in range(len(board)):
row = ""
for j in range(len(board[i])):
row += board[i][j] + " "
print(str(i) + " " + row)
draw_board(board)

print statement never gets executed in a loop

in the below posted code, the first nested for loops displays the logs or the print statemnt as expected. but the latter nested for loops which has k and l as indces never displys the logs or the print statement within it.
please let me know why the print statement
print(str(x) + ",,,,,,,,,,,,,,,,,,," + str(y))
never gets displayed despite the polygonCoordinatesInEPSG25832 contains values
python code:
for feature in featuresArray:
polygonCoordinatesInEPSG4326.append(WebServices.fetchCoordinateForForFeature(feature))
for i in range(len(polygonCoordinatesInEPSG4326)):
for j in range(len(polygonCoordinatesInEPSG4326[i])):
lon = polygonCoordinatesInEPSG4326[i][j][0]
lat = polygonCoordinatesInEPSG4326[i][j][1]
x, y = transform(inputProj, outputProj, lon, lat)
xy.append([x,y])
print ("lon:" + str(lon) + "," + "lat:" + str(lat) + "<=>" + "x:" + str(x) + "," + "y:" , str(y))
print(str(x) + "," + str(y))
print("xy[%d]: %s"%(len(xy)-1,str(xy[len(xy)-1])))
print("\n")
print("len(xy): %d"%(len(xy)))
polygonCoordinatesInEPSG25832.append(xy)
print("len(polygonCoordinatesInEPSG25832[%d]: %d"%(i,len(polygonCoordinatesInEPSG25832[i])))
xy.clear()
print("len(polygonCoordinatesInEPSG25832 = %d" %(len(polygonCoordinatesInEPSG25832)))
for k in range(len(polygonCoordinatesInEPSG25832)):
for l in range(len(polygonCoordinatesInEPSG25832[k])):
x = polygonCoordinatesInEPSG25832[k][l][0]
y = polygonCoordinatesInEPSG25832[k][l][1]
print(str(x) + ",,,,,,,,,,,,,,,,,,," + str(y))
polygonCoordinatesInEPSG25832 contain values but polygonCoordinatesInEPSG25832[k] don't.
You append it with xy but you didn't unlinked it so when you call xy.clear() it become empty. Try deep copy it instead.

Returning original string with symbols between each character

I'm trying to make my program return the exact same string but with ** between each character. Here's my code.
def separate(st):
total = " "
n = len(st + st[-1])
for i in range(n):
total = str(total) + str(i) + str("**")
return total
x = separate("12abc3")
print(x)
This should return:
1**2**a**b**c**3**
However, I'm getting 0**1**2**3**4**5**6**.
You can join the characters in the string together with "**" as the separator (this works because strings are basically lists in Python). To get the additional "**" at the end, just concatenate.
Here's an example:
def separate(st):
return "**".join(st) + "**"
Sample:
x = separate("12abc3")
print(x) # "1**2**a**b**c**3**"
A note on your posted code:
The reason you get the output you do is because you loop using for i in range(n): so the iteration variable i will be each index in st. Then when you call str(total) + str(i) + str("**"), you cast i to a string, and i was just each index (from 0 to n-1) in st.
To fix that you could iterate over the characters in st directly, like this:
for c in st:
or use the index i to get the character at each position in st, like this:
for i in range(len(st)):
total = total + st[i] + "**"
welcome to StackOverflow!
I will explain part of your code line by line.
for i in range(n) since you are only providing 1 parameter (which is for the stopping point), this will loop starting from n = 0, 1, 2, ... , n-1
total = str(total) + str(i) + str("**") this add i (which is the current number of iteration - 1) and ** to the current total string. Hence, which it is adding those numbers sequentially to the result.
What you should do instead is total = str(total) + st[i] + str("**") so that it will add each character of st one by one
In addition, you could initialize n as n = len(st)

Create string from vector

I have a numeric vector. I want to enumerate over the vector and create a string as the result. For example, if I have a vector
x = c(1, 3)
I want the resulting string to be:
y = '1x1 + 3x2'
In Python, I would do this:
l = [1, 3]
equation = ' + '.join(['{}x{}'.format(coef, i + 1) for i, coef in enumerate(l)])
str = 'y = {}'.format(equation)
How can the same thing be done in R?
You can do this:
x <- c(1, 3)
paste0(x, substitute(x), seq_along(x), collapse = " + ")
# [1] "1x1 + 3x2"
Explanation:
Get object name: substitute(x) (this returns "x")
Attach object name ("x") to x values and x index seq_alon(x) using paste0() with collapse = " + " argument.

Organize dictionary by frequency

I create a dictionary for the most used words and get the top ten. I need to sort this for the list, which should be in order. I can't do that without making a list, which I can't use. Here is my code. I am away dictionaries cannot be sorted, but i still need help.
most_used_words = Counter()
zewDict = Counter(most_used_words).most_common(10)
newDict = dict(zewDict)
keys = newDict.keys()
values = newDict.values()
msg = ('Here is your breakdown of your most used words: \n\n'
'Word | Times Used'
'\n:--:|:--:'
'\n' + str(keys[0]).capitalize() + '|' + str(values[0]) +
'\n' + str(keys[1]).capitalize() + '|' + str(values[1]) +
'\n' + str(keys[2]).capitalize() + '|' + str(values[2]) +
'\n' + str(keys[3]).capitalize() + '|' + str(values[3]) +
'\n' + str(keys[4]).capitalize() + '|' + str(values[4]) +
'\n' + str(keys[5]).capitalize() + '|' + str(values[5]) +
'\n' + str(keys[6]).capitalize() + '|' + str(values[6]) +
'\n' + str(keys[7]).capitalize() + '|' + str(values[7]) +
'\n' + str(keys[8]).capitalize() + '|' + str(values[8]) +
'\n' + str(keys[9]).capitalize() + '|' + str(values[9]))
r.send_message(user, 'Most Used Words', msg)
How would I do it so the msg prints the words in order from most used word on the top to least on the bottom with the correct values for the word?
Edit: I know dictionaries cannot be sorted on their own, so can I work around this somehow?
Once you have the values it's as simple as:
print('Word | Times Used')
for e, t in collections.Counter(values).most_common(10):
print("%s|%d" % (e,t))
Print something like:
Word | Times Used
e|4
d|3
a|2
c|2
From the Docs: most_common([n])
Return a list of the n most common elements and their counts from the
most common to the least. If n is not specified, most_common() returns
all elements in the counter. Elements with equal counts are ordered
arbitrarily:
>>> Counter('abracadabra').most_common(3)
[('a', 5), ('r', 2), ('b', 2)]
Your code can be:
from collections import Counter
c = Counter(most_used_words)
msg = "Here is your breakdown of your most used words:\n\nWords | Times Used\n:--:|:--:\n"
msg += '\n'.join('%s|%s' % (k.capitalize(), v) for (k, v) in c.most_common(10))
r.send_message(user, 'Most Used Words', msg)
import operator
newDict = dict(zewDict)
sorted_newDict = sorted(newDict.iteritems(), key=operator.itemgetter(1))
msg = ''
for key, value in sorted_newDict:
msg.append('\n' + str(key).capitalize() + '|' + str(value))
This will sort by the dictionary values. If you want it in the other order add reverse=True to sorted().

Categories