Extra newlines in python - python

I have this python code which is used to give direction to m to reach p.
Here is the code:
#!/bin/python
def displayPathtoPrincess(n,grid):
m = "m"
p = "p"
for i in range(n):
if(m in grid[i]):
m_column = grid[i].find(m)
m_row = int(i + 1)
#print "{0}x{1} \n".format(int(i + 1), m_position + 1)
if(p in grid[i]):
p_column = grid[i].find(p)
p_row = int(i + 1)
#print "{0}x{1} \n".format(int(i + 1), p_position + 1)
down_up = p_row - m_row
if(down_up > 0):
print "DOWN\n"*down_up
else:
print "UP\n"
right_left = p_column - m_column
if(right_left > 0):
print "RIGHT\n"*right_left
else:
print "LEFT\n"
m = input()
grid = []
for i in xrange(0, m):
grid.append(raw_input().strip())
displayPathtoPrincess(m,grid)
Input:
> 6
> ---
> ---
> -m-
> ---
> ---
> p--
Expected output:
DOWN
DOWN
DOWN
LEFT
My output:
DOWN
DOWN
DOWN
LEFT
As you can see in my output, the program adds a new line whenever it changes the direction. Any ideas on how to stop this new line from appearing?

You are hard-coding a newline after each 'DOWN' or 'RIGHT' every time you do this:
print "DOWN\n"*down_up
print "RIGHT\n"*right_left
The resulting strings will be 'DOWN' or 'RIGHT' followed by a newline, the specified number of times. That means that such strings will end with an unwanted newline. The smallest fix is to multiply by one fewer than the necessary number, and then add the last bit:
print "DOWN\n"*(down_up-1) + 'DOWN'
print "RIGHT\n"*(right_left-1) + 'RIGHT'
Or use str.join:
print '\n'.join("DOWN" for i in range(down_up))
print '\n'.join("RIGHT" for i in range(right_left))

Related

Why is my function breaking (ascii game using curses)? I dont understand why this error persists

The error looks like this:
Traceback (most recent call last):
File "main.py", line 136, in <module>
curses.wrapper(main)
File "/nix/store/p21fdyxqb3yqflpim7g8s1mymgpnqiv7-python3-3.8.12/lib/python3.8/curses/__init__.py", line 105, in wrapper
return func(stdscr, *args, **kwds)
File "main.py", line 130, in main
mainWindow.addstr(0, 0, buildView(windowBorder))
File "main.py", line 69, in buildView
newRow += worldRows[charPos[1]][charPos[0]]
IndexError: string index out of range
This program is supposed to take the player position, and print (using curses) the map and the player movement.
If the world DSL looks like this:
world = """
............X.....................................
.......X.......X.......X.........X...........X....
....X......X...X...X...........X.......C.X...X....
.X......X....b...X...X..X...X..X.....X........X...
...X.....................e.............X....X.....
........h..X......X...............................
..............X......X.........X........X...X.....
..X...X.....X....X......X.........................
............X...X......X.......X....d......X......
....X...X.......X...X.....X...........X......X....
.....X....X.X.....X.....X.....X...X...............
..X.X......X.X..a.......................X........
...X...X.........X..X.....g.................X.....
..X.X...X..X....X.........X........f..........X..
..................X....................X..........
"""
and the player's x, y position at start is a tuple (17, 6). The chunk of code constructing the viewport is as follows:
def buildView(border):
playerView = """"""
worldRows = [row for row in world.splitlines() if row]
counterY = -1
rows = border.splitlines()
for i, row in enumerate(rows):
newRow = ""
if i == 0 or i == len(rows):
pass
elif i == 1 or i == len(rows) - 1:
newRow = row
newRow += "\n"
else:
counterX = -6
for j, col in enumerate([char for char in row]):
if col != '#':
newRow += col
else:
charPos = (playerPos[0] + counterX,
playerPos[1] + counterY)
if charPos[0] < 0 or charPos[1] < 0 or charPos[
0] > 49 or charPos[1] > 14:
newRow += " "
else:
newRow += worldRows[charPos[1]][charPos[0]]
counterX += 1
newRow += "\n"
playerView += newRow
counterY += 1
temp1 = playerView.splitlines()
temp2 = [s for s in temp1[2]]
temp2[7] = "#"
newtemp = ""
for i in temp2:
newtemp += i
temp2 = newtemp
temp1[2] = temp2
thingy = """"""
for i in temp1:
thingy += i
thingy += "\n"
playerView = thingy
return playerView
When the program starts, it looks like this:
|=============|
|.X....X......|
|.X...X#.....X|
|.....X...X...|
|=============|
when the player types either w, a, s, or d, the player's xy is updated according to the direction they are moving, but after moving twenty six spaces to the right (player's x coord is += 26), I get the above error. Does anyone see something Im missing?
what I expect to see is this:
|=============|
|......X......|
|.X....#.X....|
|.............|
|=============|
and the player's xy coords should be (9, 43). The max xy coord of the world is (49, 14).

Python multiprocessing shared memory without copy

I'm currently working on a project for fun, involving calculating way too many numbers of the Fibonacci sequence. Thing is, I want it to go fast and I also don't want to loose too much progress if I have to do an update or have a computer issues....
So I over-engineered that, and I am currently looking to implement it with multiprocessing, but everywhere I look the only way to share memory in that case is to make a duplicate of it and that takes about an hour for (Yeah I have very big numbers)
Is there any way to share a dictionary with multiprocessing without making a copy of it?
Here is the code, currently with my last implementation using threading instead of using multiprocessing. (ignore the bad timekeeping of this, i'll fix it later)
import threading
import time
def printProgressBar(iteration, total, prefix="", suffix="", decimals=1, length=100, fill="█", printEnd="\r"):
"""
Call in a loop to create terminal progress bar
#params:
iteration - Required : current iteration (Int)
total - Required : total iterations (Int)
prefix - Optional : prefix string (Str)
suffix - Optional : suffix string (Str)
decimals - Optional : positive number of decimals in percent complete (Int)
length - Optional : character length of bar (Int)
fill - Optional : bar fill character (Str)
printEnd - Optional : end character (e.g. "\r", "\r\n") (Str)
"""
percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))
filledLength = int(length * iteration // total)
bar = fill * filledLength + "-" * (length - filledLength)
print(
f"\r{prefix} |{bar}| {percent}% {suffix} {time.strftime('%dd %H:%M:%S', time.gmtime(time.time() - start_time - 86400)).replace('31d', '0d')}",
end=printEnd,
)
# Print New Line on Complete
if iteration == total:
print()
dict47 = {0: 0, 1: 1, 2: 1}
dict47[0] = 2
def fibSequence(n):
if n not in dict47:
dict47[n] = fibSequence(n - 1) + fibSequence(n - 2)
if n > dict47[0]:
dict47[0] = n
if n > 5 and not ((n - 3) % (iterations // 100) == 0) and not ((n - 2) % (iterations // 100) == 0):
dict47.pop(n - 3, None)
return dict47[n]
def makeBackup(start, num, total):
x = threading.Thread(target=writeBackup, args=(num,), daemon=False)
y = threading.Thread(target=writeBackup, args=(num - 1,), daemon=False)
x.start()
y.start()
x.join()
y.join()
time.sleep(1)
print(
f'{num/10000000}% done after {time.strftime("%dd %H:%M:%S", time.gmtime(time.time() - start - 86400)).replace("31d", "0d")}'
)
timings = open("times.txt", "a")
timings.write(str(int(time.time() - start)) + "\n")
timings.close()
def writeBackup(num):
file = open(f".temp/fib{num}.txt", "a")
file.write(str(num) + " : " + str(dict47[num]))
file.close()
dict47.pop(num, None)
def loadDict():
from pathlib import Path
maximum = 0
for n in range(1, 100):
if Path(f".temp/fib{n*10000000}.txt").is_file():
maximum = n * 10000000
print("Maximum number found:", maximum)
if maximum != 0:
file = open(f".temp/fib{maximum}.txt", "r")
temp = "".join(file.readlines())
dict47[maximum] = int(temp.lstrip(str(maximum) + " : "))
file.close()
file = open(f".temp/fib{maximum - 1}.txt", "r")
temp = "".join(file.readlines())
dict47[maximum - 1] = int(temp.lstrip(str(maximum - 1) + " : "))
file.close()
dict47[0] = maximum
print("Dictionary loaded at ", maximum)
else:
print("No dictionary found, starting from scratch")
if __name__ == "__main__":
try:
timings = open("times.txt", "r")
lastTime = int(timings.readlines()[-1])
start_time = time.time() - lastTime
timings.close()
except:
start_time = time.time() + 86400
print("Start duration:", time.strftime("%dd %H:%M:%S", time.gmtime(time.time() - start_time)).replace("31d", "0d"))
try:
iterations = int(input("Enter the number of iterations: "))
except:
iterations = 1000000000
print(iterations, "iterations will be performed")
loadDict()
num = dict47[0]
while num < iterations:
if num == 2:
num += 248
else:
num += 250
fibSequence(num)
if num % 1000 == 0:
printProgressBar(num, iterations, prefix="Progress:", suffix="Complete", length=100)
if num % (iterations // 100) == 0:
save = threading.Thread(
target=makeBackup,
args=(start_time, num, iterations),
daemon=False,
)
save.start()
file = open("fib.txt", "a")
file.write(str(iterations) + " : " + str(fibSequence(iterations)) + "\n")
file.close()
try:
save.join()
except:
print("No save thread running, exiting...")

Python: get the range between two dotted numbers

I am trying to get the range of numbers between two dotted numbers, like 2.1.0 and 2.1.3.
My requirement is that the first two numbers need to be the same (so not 2.1.0 to 2.2.0)
What I want to get out is:
['2.1.0', '2.1.1', '2.1.2', '2.1.3']
Here is what I have tried, and it works, but I want to know if there is a better way to do it.
start = "2.1.0"
end = "2.1.3"
def get_dotted_range(start,end):
start_parts = start.split(".")
end_parts = end.split(".")
# ensure the versions have the same number of dotted sections
if len(start_parts) != len(end_parts):
return False
# ensure first 2 numbers are the same
for i in range(0,len(start_parts[:-1])):
if start_parts[i] != end_parts[i]:
# part is different betwen start and end!
return False
new_parts = []
# ensure last digit end is higher than start
if int(end_parts[-1]) >= int(start_parts[-1]):
# append the version to the return list
for i in range(int(start_parts[-1]),int(end_parts[-1]) + 1):
new_parts.append("%s.%s.%s" % (start_parts[0],start_parts[1],i))
else:
return False # end is lower than start
return new_parts
start = "2.1.0"
end = "2.1.3"
startFirst, startMiddle, startLast = map(int, start.split("."))
_, _, endLast = map(int, end.split("."))
dottedRange = [".".join(map(str, [startFirst, startMiddle, x]))
for x in range(startLast, 1+endLast)]
start = "2.1.0"
end = "2.1.3"
def get_dotted_range(start, end):
# break into number-pieces
start = start.split(".")
end = end .split(".")
# remove last number from each
x = int(start.pop())
y = int(end .pop())
# make sure start and end have the same number of sections
# and all but the last number is the same
if start != end:
return []
else:
head = ".".join(start) + "."
return [head + str(i) for i in range(x, y + 1)]
then
In [67]: get_dotted_range(start, end)
Out[67]: ['2.1.0', '2.1.1', '2.1.2', '2.1.3']
One way:
def get_dotted_range(start, end):
sparts = start.split('.')
eparts = end.split('.')
prefix = '.'.join(sparts[0:-1])
slast = int(sparts[-1])
elast = int(eparts[-1])
return [prefix + '.' + str(i) for i in range(slast, elast + 1)]
print(get_dotted_range('2.1.0', '2.1.3'))
print(get_dotted_range('2.1.9', '2.1.12'))
results in:
['2.1.0', '2.1.1', '2.1.2', '2.1.3']
['2.1.9', '2.1.10', '2.1.11', '2.1.12']
start = "2.1.0"
end = "2.1.3"
# split once to get last value
s_spl, e_spl = start.rsplit(".",1), end.rsplit(".",1)
# get first part of string to join up later
pre = s_spl[0]
# make sure first two parts are identical
if pre == e_spl[0]:
# loop in range from last element of start
# up to and including last element of end
out = ["{}.{}".format(pre, i) for i in range(int(s_spl[1]), int(e_spl[1]) + 1)]
print(out)
print(out)
['2.1.0', '2.1.1', '2.1.2', '2.1.3']
So in a function we would return a list or False:
def get_dotted_range(start,end):
s_spl, e_spl = start.rsplit(".", 1), end.rsplit(".", 1)
pre = s_spl[0]
if pre == e_spl[0]:
return ["{}.{}".format(pre, i) for i in range(int(s_spl[1]), int(e_spl[1])+1)]
return False
You should also consider the cases where a user enters incorrect data that cannot be cast to an int, the format is incorrect or they enter an empty string so you get an error indexing etc...
def get_dotted_range(start, end):
try:
s_spl, e_spl = start.rsplit(".", 1), end.rsplit(".", 1)
if s_spl[0] == e_spl[0]:
pre = s_spl[0]
return ["{}.{}".format(pre, i) for i in range(int(s_spl[1]), int(e_spl[1]) + 1)]
except ValueError as e:
return "{}: Digit expected".format(e)
except IndexError as e:
return "{}: Input format should be d.d.d ".format(e)
return False
There are other cases you may want to catch like when a user enters the start and end backwards which will end up returning an empty.

indentation error with python 3.3 when python2.7 works well

I wrote this script below which converts number to it's spelling.
no = raw_input("Enter a number: ")
strcheck = str(no)
try:
val = int(no)
except ValueError:
print("sayi degil")
raise SystemExit
lencheck = str(no)
if len(lencheck) > 6:
print("Bu sayi cok buyuk !")
raise SystemExit
n = int(no)
print(n)
def int2word(n):
n3 = []
r1 = ""
ns = str(n)
for k in range(3, 33, 3):
r = ns[-k:]
q = len(ns) - k
if q < -2:
break
else:
if q >= 0:
n3.append(int(r[:3]))
elif q >= -1:
n3.append(int(r[:2]))
elif q >= -2:
n3.append(int(r[:1]))
r1 = r
#print(n3)
nw = ""
for i, x in enumerate(n3):
b1 = x % 10
b2 = (x % 100)//10
b3 = (x % 1000)//100
if x == 0:
continue
else:
t = binler[i]
if b2 == 0:
nw = birler[b1] + t + nw
elif b2 == 1:
nw = onlar[1] + birler[b1] + t + nw
elif b2 > 1:
nw = onlar[b2] + birler[b1] + t + nw
if b3 > 0:
nw = birler[b3] + "yuz " + nw
return nw
birler = ["", " ","iki ","uc ","dort ", "bes ", "alti ","yedi ","sekiz ","dokuz "]
onlar = ["", "on ", "yirmi ", "otuz ", "kirk ", "elli ", "altmis ", "yetmis ", "seksen ", "doksan "]
binler = ["", "bin"]
print int2word(n)
This scripts works pretty well on Python2.7.
But when I try to run it with python3.3
It gives me error below:
File "numtospell.py", line 58
if x == 0:
^
TabError: inconsistent use of tabs and spaces in indentation
I've googled it for hours but cannot find a suitable solution. What do I do to fix this?
Thanks for any help.
You are mixing tabs and spaces.
Python 3 explicitly disallows this. Use spaces only for indentation.
Quoting from the Python Style Guide (PEP 8):
Spaces are the preferred indentation method.
Tabs should be used solely to remain consistent with code that is already indented with tabs.
Python 3 disallows mixing the use of tabs and spaces for indentation.
Emphasis mine.
Almost all editors can be configured to replace tabs with spaces when typing, as well as do a search and replace operation that replaces existing tabs with spaces.

Why my code is getting NZEC run time error?

Question source: SPOJ.. ORDERS
def swap(ary,idx1,idx2):
tmp = ary[idx1]
ary[idx1] = ary[idx2]
ary[idx2] = tmp
def mkranks(size):
tmp = []
for i in range(1, size + 1):
tmp = tmp + [i]
return tmp
def permutations(ordered, movements):
size = len(ordered)
for i in range(1, size): # The leftmost one never moves
for j in range(0, int(movements[i])):
swap(ordered, i-j, i-j-1)
return ordered
numberofcases = input()
for i in range(0, numberofcases):
sizeofcase = input()
tmp = raw_input()
movements = ""
for i in range(0, len(tmp)):
if i % 2 != 1:
movements = movements + tmp[i]
ordered = mkranks(sizeofcase)
ordered = permutations(ordered, movements)
output = ""
for i in range(0, sizeofcase - 1):
output = output + str(ordered[i]) + " "
output = output + str(ordered[sizeofcase - 1])
print output
Having made your code a bit more Pythonic (but without altering its flow/algorithm):
def swap(ary, idx1, idx2):
ary[idx1], ary[idx2] = [ary[i] for i in (idx2, idx1)]
def permutations(ordered, movements):
size = len(ordered)
for i in range(1, len(ordered)):
for j in range(movements[i]):
swap(ordered, i-j, i-j-1)
return ordered
numberofcases = input()
for i in range(numberofcases):
sizeofcase = input()
movements = [int(s) for s in raw_input().split()]
ordered = [str(i) for i in range(1, sizeofcase+1)]
ordered = permutations(ordered, movements)
output = " ".join(ordered)
print output
I see it runs correctly in the sample case given at the SPOJ URL you indicate. What is your failing case?

Categories

Resources