For Loops and While Loops with str and int conflictions - python

I am trying to discover how to use for loops and where strings and ints can differentiate.
I created a function calling dimension and TV size: for example
def TVDisplay(dimension, TVsize):
final = "<==="
for i in range(TVsize-2):
final = final + "=="
final = final + "==>\n"
for corner in dimension:
final = final + "< "
for edge in corner:
final = final + edge + " "
final = final + ">\n"
final = final + "<==="
for i in range(TVsize-2):
final = final + "=="
final = final + "==>\n"
return final
This function returns
<=====>
< 0 0 >
< 0 0 >
<=====>
Based on a dimension that is [['0','0'],['0','0']] and a TVsize of 2.
Now I am trying to use while loops to make it look similar, but I am running into problems at the strings and int()s
My Function looks like this:
def TVDisplay(dimension, TVsize):
final="<==="
i=0
while i < TVsize-2:
final = final + "=="
ctr+=1
final = final + "==>\n"
corner=0
while corner < dimension:
edge = 0
final = final + "< "
while edge < corner:
final = final + edge + " "
edge+=1
final = final + ">\n"
corner+=1
final = final + "<==="
while i < TVsize-2:
final = final + "=="
i+=1
final = final + "==>\n"
return final
This function returns this:
<=====>
<>
< 0 >
<=====>
I think it has to do with my middle part of code that is conflicting with strs or ints.
Does anyone have any advice how to fix this problem?
Thank you!!
EDITED::
corner=1
while corner < dimension:
final = final + "< "
edge = 0
while edge < corner:
final = final + edge + " "
edge+=1
final = final + ">\n"
corner+=1
At the:
final = final + edge + " "
line, cannot concatenate 'str' and 'int' objects appears.
my purpose to get the middle part of the loop is to spit out the middle part of the display
< 0 0 >
< 0 0 >
the last loop closes it off.
so thats my issue

Dimension is a list of lists right?
So when you call:
for corner in dimension:
for edge in corner:
It is referring to the actual object. So corner is a list and edge is an object in that list.
It would be the same as saying:
while corner < len(dimension):
edge = 0
while edge < len(dimension[corner]):
finale += dimension[corner][edge] + " "
The difference is that when you say:
for x in y
You are actually referring to the object x which is in y. However when you say:
while x < y:
x+=1
X is only an integer (in your case it is the index of the object). To access the actual object you must use y[x]. The 'in' function refers to actual objects, whereas when you use a while loop you create a counter that keeps track of an index but not the actual object.
while corner_index < len(dimension):
edge_index = 0
corner = dimension[corner_index] #retrieve the list from dimension
final = final + "< "
while edge_index < len(corner):
edge = corner[edge_index] #get the edge
final += edge + " "
edge_index+=1
final = final + ">\n"
corner_index+=1
To be even more succint:
while corner_index < len(dimension):
edge_index = 0
final = final + "< "
while edge_index < len(dimension[corner_index]):
final += dimension[corner_index][edge_index] + " "
edge_index+=1
final = final + ">\n"
corner_index+=1
As to your edit:
The way you are accessing edge (as an index integer) means you must first typecast to a string. So:
final += str(edge) + " "
You didn't have this issue initially because 'edge' referred to the actual string object '0' in your dimensions list. However, when you use while loops, 'edge' is an integer that you are using as a counter.

Related

I no longer have an alignment issue, however, when I print out my X's and O's there will be a 0 next to them. Does anyone know a different solution?

This is what I have so far, if you have any ideas please let me know. It would mean a lot to me.
a_list = list(range(1, squared_input + 1))
turn = 0
Symbol_1 = "X"
Symbol_2 = "O"
while turn <= 9:
X = 1
while X < squared_input + 1 :
print(str(a_list[X - 1]).zfill(2), end= "")
if X%board_size == 0 :
print("")
print(("--+" * (board_size - 1)), end="")
print("--")
else:
print("|", end="")
X = X + 1
turn = turn + 1
Symbol_1, Symbol_2 = Symbol_2, Symbol_1
print("You are user " + Symbol_1 + ".")
user_input = input("Please pick a slot on the game board (using numbers 1 - " + str(squared_input) + "): ")
a_list[int(user_input) - 1] = Symbol_1
The zeros come from your call to zfill which explicitly pads a string with 0 to a requested size. You call zfill(2) with a string that contains a single character. So the function pads that to length two by adding a 0.
To pad with blanks you can for example use the format() function or just something like
'%2d' % a_list[X-1]
which will pad each number to length 2 from the left with blanks, or
'%-2d' % a_list[X-1]
which will pad each number to length 2 from the right with blanks.

Increasing speed for comparative analysis using Python

I have been thinking about this problem for a while now and I was hoping that someone here would have a suggestion to considerably increase the speed of this analysis using Python.
I basically have two files. File (1) contains coordinates composed of a letter, a start and an end: e.g. "a 1000 1100" and file (2) a dataset in which each datapoint in composed of a letter and a coordinate: e.g. "p 1350". What I am trying to do with the script is to count how many datapoints fall within the borders of the coordinates, but only if the letter of the datapoint from file (2) and the coordinate from file (1) are equal. In real life datasets file (1) contains > 50K coordinates and file (2) > 50 million datapoints. Increasing the amount of datapoints exponentially increases the time my script requires to run. So I wonder if someone could come up with a more time-efficient way.
Thanks!
My script starts at # script strategy, but I first simulate a minimal example dataset:
import numpy as np
import random
import string
# simulate data
c_size = 10
d_size = 1000000
# letters
letters = list(string.ascii_lowercase)
# coordinates
c1 = np.random.randint(low=100000, high=2000000, size=c_size)
c2 = np.random.randint(low=100, high=1000, size=c_size)
# data
data = np.random.randint(low=100000, high=2000000, size=d_size)
# script strategy
# create coordinates and count dict
c_dict = {}
count_dict = {}
for start,end in zip(c1,c2):
end = start + end
c_l = random.choice(letters)
ID = c_l + '_' + str(start) + '_' + str(end)
count_dict[ID] = 0
if c_l not in c_dict:
c_dict[c_l] = [[start,end]]
else:
c_dict[c_l].append([start,end])
# count how many datapoints (x) are within the borders of the coordinates
for i in range(d_size):
d_l = random.choice(letters)
x = data[i]
if d_l in c_dict:
# increasing speed by only comparing data and coordinates with identical letter identifier
for coordinates in c_dict[d_l]:
start = coordinates[0]
end = coordinates[1]
ID = d_l + '_' + str(start) + '_' + str(end)
if x >= start and x <= end:
count_dict[ID] += 1
# print output
for ID in count_dict:
count = count_dict[ID]
print(ID + '\t' + str(count))

Check result using 4 operations based with Python

I'm struggling to make a Python program that can solve riddles such as:
get 23 using [1,2,3,4] and the 4 basic operations however you'd like.
I expect the program to output something such as
# 23 reached by 4*(2*3)-1
So far I've come up with the following approach as reduce input list by 1 item by checking every possible 2-combo that can be picked and every possible result you can get to.
With [1,2,3,4] you can pick:
[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]
With x and y you can get to:
(x+y),(x-y),(y-x),(x*y),(x/y),(y/x)
Then I'd store the operation computed so far in a variable, and run the 'reducing' function again onto every result it has returned, until the arrays are just 2 items long: then I can just run the x,y -> possible outcomes function.
My problem is this "recursive" approach isn't working at all, because my function ends as soon as I return an array.
If I input [1,2,3,4] I'd get
[(1+2),3,4] -> [3,3,4]
[(3+3),4] -> [6,4]
# [10,2,-2,24,1.5,0.6666666666666666]
My code so far:
from collections import Counter
def genOutputs(x,y,op=None):
results = []
if op == None:
op = str(y)
else:
op = "("+str(op)+")"
ops = ['+','-','*','/','rev/','rev-']
z = 0
#will do every operation to x and y now.
#op stores the last computated bit (of other functions)
while z < len(ops):
if z == 4:
try:
results.append(eval(str(y) + "/" + str(x)))
#yield eval(str(y) + "/" + str(x)), op + "/" + str(x)
except:
continue
elif z == 5:
results.append(eval(str(y) + "-" + str(x)))
#yield eval(str(y) + "-" + str(x)), op + "-" + str(x)
else:
try:
results.append(eval(str(x) + ops[z] + str(y)))
#yield eval(str(x) + ops[z] + str(y)), str(x) + ops[z] + op
except:
continue
z = z+1
return results
def pickTwo(array):
#returns an array with every 2-combo
#from input array
vomit = []
a,b = 0,1
while a < (len(array)-1):
choice = [array[a],array[b]]
vomit.append((choice,list((Counter(array) - Counter(choice)).elements())))
if b < (len(array)-1):
b = b+1
else:
b = a+2
a = a+1
return vomit
def reduceArray(array):
if len(array) == 2:
print("final",array)
return genOutputs(array[0],array[1])
else:
choices = pickTwo(array)
print(choices)
for choice in choices:
opsofchoices = genOutputs(choice[0][0],choice[0][1])
for each in opsofchoices:
newarray = list([each] + choice[1])
print(newarray)
return reduceArray(newarray)
reduceArray([1,2,3,4])
The largest issues when dealing with problems like this is handling operator precedence and parenthesis placement to produce every possible number from a given set. The easiest way to do this is to handle operations on a stack corresponding to the reverse polish notation of the infix notation. Once you do this, you can draw numbers and/or operations recursively until all n numbers and n-1 operations have been exhausted, and store the result. The below code generates all possible permutations of numbers (without replacement), operators (with replacement), and parentheses placement to generate every possible value. Note that this is highly inefficient since operators such as addition / multiplication commute so a + b equals b + a, so only one is necessary. Similarly by the associative property a + (b + c) equals (a + b) + c, but the below algorithm is meant to be a simple example, and as such does not make such optimizations.
def expr_perm(values, operations="+-*/", stack=[]):
solution = []
if len(stack) > 1:
for op in operations:
new_stack = list(stack)
new_stack.append("(" + new_stack.pop() + op + new_stack.pop() + ")")
solution += expr_perm(values, operations, new_stack)
if values:
for i, val in enumerate(values):
new_values = values[:i] + values[i+1:]
solution += expr_perm(new_values, operations, stack + [str(val)])
elif len(stack) == 1:
return stack
return solution
Usage:
result = expr_perm([4,5,6])
print("\n".join(result))

W by H grid tiles?

Imagine that we have a w by h grid, where the tiles are numbered starting at 1 in the top left corner. w (for width) and h (for height) have been stored in a function. You have access to these stored values, as long as you call them w and h. Write a program to return: The column number of a tile number given by the user. Start counting columns at column 1.
import subprocess
def template(w, h, t):
#w and h are memory locations that already contain values
tile = t
sum = ((t - 1) // w) + 1
#END OF YOUR CODE
failed = 0
width = 1
while width <= 3:
height = 1
while height <= 3:
tile = 1
while tile <= width * height:
result = template(width, height, tile)
col = (tile - 1) % width + 1
if (result == col):
print "On a " + str(width) + " by " + str(height) +" board, with tile " + str(tile) +", col is " + str(col) + ", you got it RIGHT!"
else:
print "On a " + str(width) + " by " +:str(height)%+" board, with tile " + str(tile)%+", col is " + str(col) + ", you got: " + str(result)
failed = 1
tile += 1
height += 1
width += 1
if (failed == 0):
print "Your code is CORRECT!"
print "Please check your code, at least one test case did not pass."
I am almost there I think, but this formula isn't quite right and I'm out of ideas.
See below pseudo code, this approach should work for you,
# divide t by h, the tile should reside in the next row
tileRow = (t/h)+1
# get the reminder of the division, that's the column number
tileColumn = t%h
see the sample code I tried below
>>> w = 5
>>> h = 10
>>> t =36
>>> tileRow = (t/h)+1
>>> tileRow
4 # the tile is in the 4th row
>>> tileColumn = t%h
>>> tileColumn
6 # the tile is in the 6th column
>>>
You may also have to check if the tile number is within in range, in the above example its w x h (50)
Please comment if you need anymore clarification. If this resolves your problem you may accept and vote the answer
To create the grid, use a list comprehension.
grid=[list(range(x,x+w))for x in range(1,w*h,w)]
To find the column number of t, find the remainder of t divided by w:
t%w
So the function would be:
def template(w,h,t):
grid=[list(range(x,x+w))for x in range(1,w*h,w)]
return t%w
Example:
template(6,5,22)
Output:
4

Python 3.3 - Create 3D-mesh as Wavefront obj-file from regular spaced vertices

I am writing a simple command line program in Python 3.3 which reads a text file of xyz-coordinates and outputs a the equivalent triangle faces in between. The export format are Wavefront obj-files (https://en.wikipedia.org/wiki/Wavefront_.obj_file). The algorthm is solely intended to work with regular spaced points from high resolution satellite scans of the earth. Actually, I am using a set of about 340000 points and creating 2 triangles in between a vertex quadrupel. The outer iteration goes in x-direction while the inner iteration is over the y-direction. So, pairs of triangle faces are creates for every vertex in y-direction until it moves on in x-direction and repeats the process. I will show you the principle pattern (the lines are the face edges):
v1--v5--v9
| \ | / |
v2--v6--v10
| / | \ |
v3--v7--v11
| \ | / |
v4--v8--v12
The code seems to work in way as importing the file in Blender or MeshLab gives reasonable results, except for one thing: All stripes of face pairs seem to be not connected with their neighbors along the x-axis. A rendered picture which demonstrates the problem:
unconnected stripes.
Normally, there shouldn't be an vertical offset between different face-stripes because they share the same vertices along their interior border(-line). Tests with less vertices and more common low coordinate values succeeded. The method was working perfectly fine. Maybe the problem lies not within my mesh generator but within the coordinate limitations of Blender, MeshLab, etcetera.
Here is the function which generates the faces and stitches everythin together in an return-string:
def simpleTriangMesh(verts):
printAll("--creating simple triangulated mesh", "\n")
maxCoords = [max(verts[0]), max(verts[1]), max(verts[2])]
minCoords = [min(verts[0]), min(verts[1]), min(verts[2])]
printAll("max. coordinates (xyz): \n", maxCoords, "\n")
printAll("min. coordinates (xyz): \n", minCoords, "\n")
xVerts = 0 # amount of vertices in x-direction
yVerts = 0 # amount of vertices in y-direction
faceAmount = 0 # amount of required faces to skin grid
i = 0
temp = verts[0][0]
while(i < len(verts[0])):
if(temp < verts[0][i]):
yVerts = int(i)
break
temp = verts[0][i]
i += 1
xVerts = int(len(verts[0]) / float(yVerts))
faceAmount = ((xVerts - 1) * (yVerts - 1)) * 2
printAll("vertices in x direction: ", xVerts, "\n")
printAll("vertices in y direction: ", yVerts, "\n")
printAll("estimated amount of triangle faces: ",
faceAmount, "\n")
printAll("----generating vertex triangles representing the faces", "\n")
# list of vertex-index quadrupels representing the faces
faceList = [[0 for line in range(0, 3)] for face in range(0, int(faceAmount))]
f = 0
v = 0
# rather to draw hypotenuse of the triangles from topleft to bottomright
# or perpendicular to that (topright to bottomleft)
tl = True # the one that changes in y-direction
tl_rem = False # to remember the hypotenuse direction of the last topmost faces
while(f < len(faceList)):
# prevent creation of faces at the bottom line
# + guarantees that v = 1 when creating the first face
if(( v % yVerts ) == 0):
v += 1
tl = not tl_rem
tl_rem = tl
if(tl):
faceList[f][0] = v
faceList[f][1] = v + yVerts
faceList[f][2] = v + yVerts + 1
f += 1
faceList[f][0] = v
faceList[f][1] = v + yVerts + 1
faceList[f][2] = v + 1
else:
faceList[f][0] = v
faceList[f][1] = v + yVerts
faceList[f][2] = v + 1
f += 1
faceList[f][0] = v + 1
faceList[f][1] = v + yVerts
faceList[f][2] = v + yVerts + 1
f += 1
v += 1
tl = not tl
printAll("----preparing obj-file-content for export", "\n")
rectMesh_Obj = "" # string containing the mesh in obj-format (ascii)
tempVerts = ""
tempFaces = ""
row = 0
while(row < len(verts[0])):
# temp = ("v" + " " + str(verts[0][row]) + " " + str(verts[1][row])
# + " " + str(verts[2][row]) + "\n")
temp = ("v" + " " + str(verts[0][row]) + " " + str(verts[2][row])
+ " " + str(verts[1][row]) + "\n")
tempVerts += temp
row += 1
row = 0
while(row < len(faceList)):
temp = ("f"
+ " " + str(int(faceList[row][0]))
+ " " + str(int(faceList[row][1]))
+ " " + str(int(faceList[row][2]))
# + " " + str(int(faceList[row][3]))
+ "\n")
tempFaces += temp
row += 1
rectMesh_Obj += tempVerts + tempFaces
return(rectMesh_Obj)
The verts-variable which is inputted into the function has the form of a 2-dimensional list, similar to:
# x y z
vertsExample = [[3334, 3333, 3332], [2555, 2554, 2553], [10.2, 5.2, 6.7]]
I hope some of you can help me out of the misery. If something requires more explanation, please let me know and I will add it to the first post.
I finally solved the issue. The problem wasn't in my mesh generator program. Blender and MeshLab (and most likely other 3D-Programs as well) do some weird things when the coordinates of vertices are too big. If am reducing the real world geographically projected coordinates to smaller relative coordinates everything works just fine (https://dl.dropboxusercontent.com/u/13547611/meshGenWorking001.png).
My guess:
The Wavefront obj-format has too limited byte-sizes for its numbers. or to be more correct: Common 3D-Programs do not expect the numbers to be so big like the real world ones. This way they interpret what they get in a confusing manner.
I hope this solution helps somebody in the future !

Categories

Resources