How do I swap the rows and different values in my function? - python

I am currently in a coding class and I am trying to learn Python (Python 3) and I have written some code here for an assignment but I am apparently getting the swapping wrong and I don't know how to fix it. I have the assignment's instructions and I also have a comment on my code that I need help understanding. Can someone please show me how to flip the rows by swapping the different values?
Here are the instructions:
Here is my code:
def flipIt(array):
for i in range(len(array)):
length = len(array[i])
for j in range(length // 2):
temp = array[i][j]
array[i][j] = array[i][length - 1 - j]
array[i][length - 1 - j] = temp
pic = [['#', ' ', ' ', ' ', ' ', '#'],
['#', '#', ' ', ' ', ' ', '#'],
['#', ' ', '#', ' ', ' ', '#'],
['#', ' ', ' ', '#', ' ', '#'],
['#', ' ', ' ', ' ', '#', '#'],
['#', ' ', ' ', ' ', ' ', '#']]
flipIt(pic)
for i in pic:
for j in i:
print(j,end=' ')
print()
Here is the comment:
How do I do what the comment says?

Mmh, it took me some time to realize the problem because flipping this picture vertically and horizontally gives the same result. In your case, what you want to do is:
def flipIt(array):
height = len(array)
for i in range(len(array) // 2):
temp = array[i]
array[i] = array[height-1-i]
array[height-1-i] = temp
# No need for return because it is modified in place
pic = [['#', ' ', ' ', ' ', ' ', '#'],
['#', '#', ' ', ' ', ' ', '#'],
['#', ' ', '#', ' ', ' ', '#'],
['#', ' ', ' ', '#', ' ', '#'],
['#', ' ', ' ', ' ', '#', '#'],
['#', ' ', ' ', ' ', ' ', '#']]
flipIt(pic)
for i in pic:
for j in i:
print(j,end=' ')
print()
Of course, as Sam Stafford suggested, you can make it even simpler (given that you are allowed) with
def flipIt(array):
array.reverse()

The flipIt function is unneeded since Python has a built-in way to do this. All you need to do is replace:
flipIt(pic)
with:
pic.reverse()
(You could also do something like flipIt = lambda img: img.reverse() if you wanted an extra layer of abstraction in there, or because the assignment required you to have a function that was specifically called flipIt.)
The list.reverse() method operates on any list and does an in-place reversal of its elements. Since pic is a list of rows in the image, reversing the order has the effect of flipping it vertically.
You can also simplify your print loop by using str.join() to turn each row into a single string.
>>> pic = [['#', ' ', ' ', ' ', ' ', '#'],
... ['#', '#', ' ', ' ', ' ', '#'],
... ['#', ' ', '#', ' ', ' ', '#'],
... ['#', ' ', ' ', '#', ' ', '#'],
... ['#', ' ', ' ', ' ', '#', '#'],
... ['#', ' ', ' ', ' ', ' ', '#']]
>>> pic.reverse() # flip the rows from top to bottom
>>> for row in pic:
... print(' '.join(row))
...
# #
# # #
# # #
# # #
# # #
# #

Your current code actually works just fine. You just forgot to return your flipped array from your function:
def flipit(array):
for i in range(len(array)):
length = len(array[i])
for j in range(length // 2):
temp = array[i][j]
array[i][j] = array[i][length - 1 - j]
array[i][length -1 -j] = temp
return array
pic = [['#', ' ', ' ', ' ', ' ', '#'],
['#', '#', ' ', ' ', ' ', '#'],
['#', ' ', '#', ' ', ' ', '#'],
['#', ' ', ' ', '#', ' ', '#'],
['#', ' ', ' ', ' ', '#', '#'],
['#', ' ', ' ', ' ', ' ', '#']
]
x = flipit(pic)
print(x)

Related

How to make a function that lays mines to random squares on nested list?

The field is created like this:
field = []
for row in range(10):
field.append([])
for col in range(15):
field[-1].append(" ")
Tuples represent free squares where mines can be layed
free = []
for x in range(15):
for y in range(10):
free.append((x, y))
I have to lay the mines trough this function:
def lay_mines(field, free, number_of_mines):
for _ in number_of_mines:
mines = random.sample(free, number_of_mines)
field(mines) = ["x"]
I was thinking using random.sample() or random.choice(). I just can't get it to work. How can I place the string "x" to a certain random coordinate?
import random
def lay_mines(x, y, number_of_mines=0):
f = [list(' ' * x) for _ in range(y)]
for m in random.sample(range(x * y), k=number_of_mines): # random sampling without replacement
f[m % y][m // y] = 'X'
return f
field = lay_mines(15, 10, 20)
print(*field, sep='\n')
Prints:
['X', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
[' ', ' ', ' ', ' ', 'X', ' ', ' ', ' ', 'X', ' ', ' ', ' ', ' ', ' ', ' ']
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'X', ' ', ' ', ' ', ' ', ' ', ' ']
[' ', ' ', 'X', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
[' ', ' ', 'X', ' ', ' ', ' ', ' ', 'X', 'X', ' ', ' ', ' ', ' ', ' ', ' ']
[' ', ' ', ' ', ' ', ' ', ' ', 'X', ' ', ' ', ' ', ' ', 'X', ' ', ' ', ' ']
[' ', 'X', ' ', ' ', 'X', ' ', ' ', ' ', ' ', 'X', ' ', ' ', ' ', ' ', ' ']
[' ', ' ', 'X', 'X', 'X', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
[' ', ' ', ' ', ' ', ' ', 'X', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'X']
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'X', ' ', 'X', ' ', ' ', ' ', ' ']

Why element does not replace in numpy.array?

I want to assign a new value to [i + 1][j] of array, but it seems there is a problem.
a = np.array(['#', '#', '#', '#', '#', '#','#', ' ', ' ', 'A', ' ', '#',
'#', ' ', '#', 'P', ' ', '#',
'#', ' ', ' ', ' ', ' ', '#',
'#', 'P', ' ', ' ', ' ', '#',
'#', '2', ' ', ' ', ' ', '#',
'#', '#', '#', '#', '#', '#'])
print(len(a))
b = np.reshape(a,(7,6))
i = 0
j = 0
print(b[i + 1][j])
b[i + 1][j] = 'AP'
print(b[i + 1][j])
output:
#
A
How can I assign "AP" instead of "#" ?
b.dtype (see data type objects) is <U1 which is a unicode string of length 1.
you could fix that with
a = np.array(['#',..., '#'], dtype='<U2')
which will then accept strings up to length 2.

Issue using regex to split strings with a list of delimiters

I am using this function to split a text in words and separators while preserving them
import re
def split_text_in_words(phrase_text, separators=[" "]):
separator_regex = """({0})""".format("""|""".join(separators))
return [f for f in re.split(separator_regex,phrase_text) if len(f) > 0]
I am using this code like this:
>>> split_text_in_words('Mary & his family has a?nice.house at #157, at the beach? Of course! it is great. I owe her 40$ so I plan to pay my debt weekly at 3% interest :) "no comment"', separators=[' ', '\?', '\*', '\.', ',', ';', ':', "'", '"', '-', '\?', '!', '#', '\$', '%', '^', '&'])
['Mary', ' ', '&', ' ', 'his', ' ', 'family', ' ', 'has', ' ', 'a', '?', 'nice', '.', 'house', ' ', 'at', ' ', '#', '157', ',', ' ', 'at', ' ', 'the', ' ', 'beach', '?', ' ', 'Of', ' ', 'course', '!', ' ', 'it', ' ', 'is', ' ', 'great', '.', ' ', 'I', ' ', 'owe', ' ', 'her', ' ', '40', '$', ' ', 'so', ' ', 'I', ' ', 'plan', ' ', 'to', ' ', 'pay', ' ', 'my', ' ', 'debt', ' ', 'weekly', ' ', 'at', ' ', '3', '%', ' ', 'interest', ' ', ':', ')', ' ', '"', 'no', ' ', 'comment', '"']
This looks good so far and is precisely what I want. However when adding parens on the list of separators and I happen to have the text starting with a parens, the splitting gears don't kick in:
>>> split_text_in_words('(as if it was not aware) Mary & his family has a?nice beach* house at #157, at the beach? Of course! it is great. I owe her 40$ so I plan to pay my debt weekly at 3% interest :) "no comment"', separators=[' ', '\?', '\*', '\.', ',', ';', ':', "'", '"', '-', '\?', '!', '#', '\$', '%', '^', '&', '\*', '\(', '\)'])
['(as', ' ', 'if', ' ', 'it', ' ', 'was', ' ', 'not', ' ', 'aware', ')', ' ', 'Mary', ' ', '&', ' ', 'his', ' ', 'family', ' ', 'has', ' ', 'a', '?', 'nice', ' ', 'beach', '*', ' ', 'house', ' ', 'at', ' ', '#', '157', ',', ' ', 'at', ' ', 'the', ' ', 'beach', '?', ' ', 'Of', ' ', 'course', '!', ' ', 'it', ' ', 'is', ' ', 'great', '.', ' ', 'I', ' ', 'owe', ' ', 'her', ' ', '40', '$', ' ', 'so', ' ', 'I', ' ', 'plan', ' ', 'to', ' ', 'pay', ' ', 'my', ' ', 'debt', ' ', 'weekly', ' ', 'at', ' ', '3', '%', ' ', 'interest', ' ', ':', ')', ' ', '"', 'no', ' ', 'comment', '"']
The first parens remains attached to the word. I can work around this issue by simply appending a space at beginning:
>>> split_text_in_words(' (as if it was not aware) Mary & his family has a?nice beach* house at #157, at the beach? Of course! it is great. I owe her 40$ so I plan to pay my debt weekly at 3% interest :) "no comment"', separators=[' ', '\?', '\*', '\.', ',', ';', ':', "'", '"', '-', '\?', '!', '#', '\$', '%', '^', '&', '\*', '\(', '\)'])
[' ', '(', 'as', ' ', 'if', ' ', 'it', ' ', 'was', ' ', 'not', ' ', 'aware', ')', ' ', 'Mary', ' ', '&', ' ', 'his', ' ', 'family', ' ', 'has', ' ', 'a', '?', 'nice', ' ', 'beach', '*', ' ', 'house', ' ', 'at', ' ', '#', '157', ',', ' ', 'at', ' ', 'the', ' ', 'beach', '?', ' ', 'Of', ' ', 'course', '!', ' ', 'it', ' ', 'is', ' ', 'great', '.', ' ', 'I', ' ', 'owe', ' ', 'her', ' ', '40', '$', ' ', 'so', ' ', 'I', ' ', 'plan', ' ', 'to', ' ', 'pay', ' ', 'my', ' ', 'debt', ' ', 'weekly', ' ', 'at', ' ', '3', '%', ' ', 'interest', ' ', ':', ')', ' ', '"', 'no', ' ', 'comment', '"']
But I'm concerned why this happening and if the strategy (hack, really) of adding a space at the beginning does not reassure me that it won't fail in some other more subtle case
Why is this happening, and would the hack/fix of appending a space at the beginning work in general?
The problem is the unescaped ^. You should probably escape all punctuation characters you use with something like:
split_text_in_words(
'(as if it was not aware) Mary & his family',
separators=["\\" + c for c in " ?*.,;:'\"-!#$%^&()"]
)
Maybe, even do it in the function:
import re
def split_text_in_words(phrase_text, separators=[" "]):
inter = "|".join(
re.sub(r"(^|[^\\])([^A-Za-z0-9])", r"\\\2", sep) for sep in separators
)
# Add the backslash if not already present for every non-alphanumeric
# character.
separator_regex = "({0})".format(inter)
return [f for f in re.split(separator_regex, phrase_text) if len(f) > 0]
Problem is use of unescaped ^ in your separator that becomes part of your splitting regex. ^ is a special regex meta-character that means start anchor.
You must escape it as this:
separators=[' ', '\?', '\*', '\.', ',', ';', ':', "'", '"', '-', '\?', '!', '#', '\$', '%', '\^', '&', '\*', '\(', '\)']
^ marks the beginning of the string so it must be escaped in the separator list: '\^'
A more comfortable and safer way would be to not escape the separators in the parameter but in the function instead:
separator_regex = """({0})""".format("""|""".join(map(re.escape, separators)))

For loop not working as intended

I am in the middle of my course work and I am now having trouble with one of my for loops.
def update():
update=[]
update1=[]
with open('Stock2.txt','r') as stockFile:
for eachLine in stockFile:
eachLine=eachLine.strip().split()
update.append(eachLine)
update.remove(update[0])
stockFile.close()
with open('Stock2.txt','r') as stockFile:
for eachLine in stockFile:
eachLine=eachLine.strip().split(' ')
update1.append(eachLine)
update1.remove(update1[0])
for eachList in update1:
loopCon=-1
for eachItem in eachList:
loopCon+=1
if eachItem=='':
eachList[loopCon]=' '
count=-1
for eachList in update1:
for eachItem in eachList:
count+=1
if eachItem != ' ':
print(count)
The last for loop that I have been working on is looping ok but when I add one to count every time it loops on the for loop 'for eachItem in eachList:' it comes up with random numbers as follows:
0 10 14 21 28 35 36 46 62 69 76 83 84 94 111
Here is the stock file I am using - Stock2.txt
GTIN-8 Product-Name Price(£) CSL ROL TSL
95820194 Windows-10-64bit 119.99 0 1 3
68196167 Cheese 1.00 0 3 8
62017014 Bread 0.93 0 3 9
86179616 10tb-memory-stick 916.96 0 0 4
19610577 Freddo 0.15 0 2 9
So on.
Is there anything I have done wrong whilst doing this as I probably would not be able to detect it that easily as I have only been doing python for almost 1 year.
Thank you for your time.
You increment count outside the if that prints. Try this instead:
for eachList in update1:
for eachItem in eachList:
if eachItem != ' ':
count+=1
print(count)
If I put a print update1 statement before your last for loop, i.e., before the statement for eachList in update1:, I get the following output:
[['95820194', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'Windows-10-64bit', ' ', ' ', ' ', '119.99', ' ', ' ', ' ', ' ', ' ', ' ', '0', ' ', ' ', ' ', ' ', ' ', ' ', '1', ' ', ' ', ' ', ' ', ' ', ' ', '3'], ['68196167', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'Cheese', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '1.00', ' ', ' ', ' ', ' ', ' ', ' ', '0', ' ', ' ', ' ', ' ', ' ', ' ', '3', ' ', ' ', ' ', ' ', ' ', ' ', '8'], ['62017014', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'Bread', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '0.93', ' ', ' ', ' ', ' ', ' ', ' ', '0', ' ', ' ', ' ', ' ', ' ', ' ', '3', ' ', ' ', ' ', ' ', ' ', ' ', '9'], ['86179616', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '10tb-memory-stick', ' ', ' ', '916.96', ' ', ' ', ' ', ' ', ' ', ' ', '0', ' ', ' ', ' ', ' ', ' ', ' ', '0', ' ', ' ', ' ', ' ', ' ', ' ', '4'], ['19610577', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'Freddo', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '0.15', ' ', ' ', ' ', ' ', ' ', ' ', '0', ' ', ' ', ' ', ' ', ' ', ' ', '2', ' ', ' ', ' ', ' ', ' ', ' ', '9']]
So by this it seems the output isnt random at all. What you are doing is traversing each list inside the list update1, and you are incrementing count each time you get an element in eachItem.
However you are printing count only when eachItem != ' '. So as you can see it prints 0 when eachItem == '95820194', and then it prints 10 when eachItem == 'Windows-10-64bit', and so on. Though it is incremented even when eachItem == ' ', just not printed.

Partitioning a string in Python by a regular expression

I need to split a string into an array on word boundaries (whitespace) while maintaining the whitespace.
For example:
'this is a\nsentence'
Would become
['this', ' ', 'is', ' ', 'a' '\n', 'sentence']
I know about str.partition and re.split, but neither of them quite do what I want and there is no re.partition.
How should I partition strings on whitespace in Python with reasonable efficiency?
Try this:
s = "this is a\nsentence"
re.split(r'(\W+)', s) # Notice parentheses and a plus sign.
Result would be:
['this', ' ', 'is', ' ', 'a', '\n', 'sentence']
Symbol of whitespace in re is '\s' not '\W'
Compare:
import re
s = "With a sign # written # the beginning , that's a\nsentence,"\
'\nno more an instruction!,\tyou know ?? "Cases" & and surprises:'\
"that will 'lways unknown **before**, in 81% of time$"
a = re.split('(\W+)', s)
print a
print len(a)
print
b = re.split('(\s+)', s)
print b
print len(b)
produces
['With', ' ', 'a', ' ', 'sign', ' # ', 'written', ' # ', 'the', ' ', 'beginning', ' , ', 'that', "'", 's', ' ', 'a', '\n', 'sentence', ',\n', 'no', ' ', 'more', ' ', 'an', ' ', 'instruction', '!,\t', 'you', ' ', 'know', ' ?? "', 'Cases', '" & ', 'and', ' ', 'surprises', ':', 'that', ' ', 'will', " '", 'lways', ' ', 'unknown', ' **', 'before', '**, ', 'in', ' ', '81', '% ', 'of', ' ', 'time', '$', '']
57
['With', ' ', 'a', ' ', 'sign', ' ', '#', ' ', 'written', ' ', '#', ' ', 'the', ' ', 'beginning', ' ', ',', ' ', "that's", ' ', 'a', '\n', 'sentence,', '\n', 'no', ' ', 'more', ' ', 'an', ' ', 'instruction!,', '\t', 'you', ' ', 'know', ' ', '??', ' ', '"Cases"', ' ', '&', ' ', 'and', ' ', 'surprises:that', ' ', 'will', ' ', "'lways", ' ', 'unknown', ' ', '**before**,', ' ', 'in', ' ', '81%', ' ', 'of', ' ', 'time$']
61
Try this:
re.split('(\W+)','this is a\nsentence')

Categories

Resources