How to handle index out of range - python

Im building an A star algorithm and i want to store the 8 possible directions to move to in a dictionary like so: ["NW: a location north west, which i call from a 2D list which stores all units on my map]
For the North west example, i would call the unit like so:
["NW": map[p.x -1][p.y-1]]
which stores the top left (or NW) unit (p is the starting location unit, from which i call its x and y coordinate. map is what I'm using to illustrate my 2D list which holds all the units on my grid).
I have to do a similar thing for all 8 directions around a starting unit.
The issue is that the starting unit could at any point be on the edge of the map, so if i try to go NW,W, or SW when the start node is at the left border of my map, ill obviously get an index out of bounds error of some sort.
how can i efficiently test for all the 8 cases at once? i don't want to add them all to my dictionary individually and surround them each with their own try statement. In essence i want to add this piece of code into my program:
dic = ["NW": map[p.x -1][p.y-1], "N": map[p.x][p.y-1], "NE" map[p.x
+1][p.y-1], ...]
and so on, for all 8 directions.

Related

I want to make multiple list of coordinates from a single list of coordinates with can make a close loop

input_list = [(2282.405, -89.9415, 266.1414), (2276.534, -89.9526, 266.9091), (2276.534, -83.9573, 266.9091), (2282.405, -83.9464, 266.1414), (2288.276, -77.9407, 265.3738), (2294.148, -77.9301, 264.6062), (2294.148, -83.9247, 264.6062), (2288.276, -83.9356, 265.3738), (2282.405, -71.9563, 266.1414), (2288.276, -71.9459, 265.3738), (2282.405, -77.9514, 266.1414), (2288.276, -89.9304, 265.3738), (2276.534, -77.962, 266.9091), (2294.148, -71.9355, 264.6062), (2276.534, -71.9667, 266.9091), (2294.148, -89.9193, 264.6062)]
Requirement is to make 9 list which will contain coordinates of 4 points which forms a closed loop
I tried some ways by find the distances and then creating sets but the issue is with point which lies in the middle , there are 4 combinations comming up.
Requirement is to get exactly 9 list using python as shown in image , ( list will contains coordinates of 4 grids )
the sequence should be always anticlockwise
Requiring to get "counterclockwise" answer, in a 3d assignment is tricky. A leaf has 2 sides, but I can imagine that the actual requirement is to always loop on the same order, and that if an edge is counted once "a to b", it will be counted "b to a" the next time.
Also your example look planar and "grid like". If this is really the assignment, I'd suggest using numpy eigenvector functions to reduce your coordinate system to 2d, then a transformation matrix to have your points aligned to (0,0),(0,1),etc.
To find this transformation matrix, take one point randomly, find the closest one on the x dimension, the closest one on the y dimension.
I'd say your assignment is more of a math assignment
Edit : I've given it a little more though. I really think that the simpliest answer is to make the most of the fact that :
You can simply enough find a corner point, and a corner square from your input,
A 3x3 grid of unitary squares can be transformed into your input, using the corner square as reference for the first unitary square. You just have to find the correct matrix for the matrix multiplication,
You can write by hand the loops for the unitary square, use a matrix addition to translate it as any square in the grid and project them using the previous matrix.

Getting Keys Within Range/Finding Nearest Neighbor From Dictionary Keys Stored As Tuples

I have a dictionary which has coordinates as keys. They are by default in 3 dimensions, like dictionary[(x,y,z)]=values, but may be in any dimension, so the code can't be hard coded for 3.
I need to find if there are other values within a certain radius of a new coordinate, and I ideally need to do it without having to import any plugins such as numpy.
My initial thought was to split the input into a cube and check no points match, but obviously that is limited to integer coordinates, and would grow exponentially slower (radius of 5 would require 729x the processing), and with my initial code taking at least a minute for relatively small values, I can't really afford this.
I heard finding the nearest neighbor may be the best way, and ideally, cutting down the keys used to a range of +- a certain amount would be good, but I don't know how you'd do that when there's more the one point being used.Here's how I'd do it with my current knowledge:
dimensions = 3
minimumDistance = 0.9
#example dictionary + input
dictionary[(0,0,0)]=[]
dictionary[(0,0,1)]=[]
keyToAdd = [0,1,1]
closestMatch = 2**1000
tooClose = False
for keys in dictionary:
#calculate distance to new point
originalCoordinates = str(split( dictionary[keys], "," ) ).replace("(","").replace(")","")
for i in range(dimensions):
distanceToPoint = #do pythagors with originalCoordinates and keyToAdd
#if you want the overall closest match
if distanceToPoint < closestMatch:
closestMatch = distanceToPoint
#if you want to just check it's not within that radius
if distanceToPoint < minimumDistance:
tooClose = True
break
However, performing calculations this way may still run very slow (it must do this to millions of values). I've searched the problem, but most people seem to have simpler sets of data to do this to. If anyone can offer any tips I'd be grateful.
You say you need to determine IF there are any keys within a given radius of a particular point. Thus, you only need to scan the keys, computing the distance of each to the point until you find one within the specified radius. (And if you do comparisons to the square of the radius, you can avoid the square roots needed for the actual distance.)
One optimization would be to sort the keys based on their "Manhattan distance" from the point (that is, add the component offsets), since the Euclidean distance will never be less than this. This would avoid some of the more expensive calculations (though I don't think you need and trigonometry).
If, as you suggest later in the question, you need to handle multiple points, you can obviously process each individually, or you could find the center of those points and sort based on that.

select the bigger ball

I've got an array of data filled with "#" and "." for example it display something like this :
...........#############..............................
.........################..................#######....
........##################................#########...
.......####################..............###########..
........##################................#########...
.........################..................#######....
...........#############..............................
I want to create an algorithm that find the bigger ball and erase the smaller one.
I was thinking of using the longest sequence of "#" to know what is the diameter.
So i've got something like this :
x = 0
longest_line = 0
for i in range(0, nbLine) :
for j in range(0, nbRaw) :
if data[i, j] = red :
x = x+1
if data[i, j+1] != red:
And i don't know what to do next..
I would use some sort of a segmentation algorithm, and then simply count the number of pixels in each object. Then simply erase the smaller one, which should be easy as you have a tag of the object.
The segmentation algorithms typically work like this.
Perform a raster scan, starting upper left, working towards bottom right.
As you see a #, you know you have an object. Check it's neighbors.
If the neighbors have a previously assigned value, assign that value to it
If there there are multiple values, put that into some sort of a table, which after you are done processing, you will simplify.
So, for a very simple example:
...##...
.######.
...##...
Your processing will look like:
00011000
02111110
00011000
With a conversion such that:
2=>1
Apply the look up table, and all objects will be tagged with a 1 value. Then simply count the number of pixels, and you are done.
I'll leave the implementation to you;-)
Get your data into a nicer array structure
Perform connected component labelling
Count the number of elements with each label (ignoring the background label)
Choose the label with the largest number of elements
Do you olways have only 2 shapes like this? Because in this case, you could also use the python regular expression library. This code seems to do the trick for your example (I copied your little drawing in a file and named it "balls.txt"):
import re
f = open("balls.txt", "r")
for line in f :
balls = re.search("(\.+)(#+)(\.+)(#*)(\.+)", line)
dots1 = balls.groups()[0]
ball1 = balls.groups()[1]
dots2 = balls.groups()[2]
ball2 = balls.groups()[3]
dots3 = balls.groups()[4]
if len(ball1) < len(ball2):
ball1 = ball1.replace('#', '.')
else:
ball2 = ball2.replace('#', '.')
print "%s%s%s%s%s" % (dots1, ball1, dots2, ball2, dots3)
And this is what I get:
...........#############..............................
.........################.............................
........##################............................
.......####################...........................
........##################............................
.........################.............................
...........#############..............................
I hope this can give you some ideas for the resolution of your problem
Assuming the balls don't touch:
Assuming exactly two balls
Create two ball objects, (called balls 0 and 1) each owns a set of points. Points are x,y pairs.
scan each row from top to bottom, left to right within each line.
When you see the first #, assign it to ball 0 (add it’s x,y cords to the set owned by the ball 0 object).
When you see any subsequent #, add it to ball 0 if it is adjacent to any point already in ball 0; otherwise add it to ball 1. (If the new # is at x, y we just test (x+1,y) is in set, (x-1, y) is in set, (x, y+1) is in set, (x, y-1) is in set, and the diagonal neighbors)
When the scan is complete, the list sizes reveal the larger ball. You then have a list of the points to be erased in the other ball’s points set.

GPS co-ordinate search --R-trees

I have a list of lists in the form of
[ [ x1,.....,x8],[x1,.......,x8],...............,[x1,.....x[8]] ] . The number of lists in that list can go upto a million. Each list has 4 gps co-ordinates which show the four points of a rectangle ( assumed that each segment is in the form of a rectangle].
Problem : Given a new point, I need to determine which segment the point falls on and create a new one if it falls in none of them. I am not uploading the data into MySQL as of now, it comes in as a simple text file. I find out the co-ordinates from the text file for any given car.
What I tried : I am thinking of using R-trees to find all points which are near to the given point . ( Near== 200 meters maximum) . But even in R-trees, there seem to be too many options . R,R*,Hilbert.
Q1. Which one should be opted for ?
Q2. Is there a better option than R-trees?Can something be done by searching faster within the list ?
Thanks a lot.
[ {a1:[........]},{a2:[.......]},{a3:[.........]},.... ,{a20:[.....]}] .
Isn't the problem "find whether a given point falls within a certain rectangle in 2D space"?
That could be separated dimensionally, couldn't it? Give each rectangle an ID, then separate into lists of one-dimensional ranges ((id, x0, x1), (id, y0, y1)) and find all the ranges in both dimensions the point falls in. (I'm fairly sure there are very efficient algorithms for this. Heck, you could even leverage, say, sqlite already.) Then just intersect the ID sets you get and you should find all rectangles the point falls in, if any. (Of course you can exit early if either of the single dimensional queries returns no result.)
Not sure if this'd be faster or smarter than R-trees or other spatial indexes though. Hope this helps anyway.
import random as ra
# my _data will hold tuples of gps readings
# under the key of (row,col), knowing that the size of
# the row and col is 10, it will give an overall grid coverage.
# Another dict could translate row/col coordinates into some
# more usefull region names
my_data = {}
def get_region(x,y,region_size=10):
"""Build a tuple of row/col based on
the values provided and region square dimension.
It's for demonstration only and it uses rather naive calculation as
coordinate / grid cell size"""
row = int(x / region_size)
col = int(y / region_size)
return (row,col)
#make some examples and build my_data
for loop in range(10000):
#simule some readings
x = ra.choice(range(100))
y = ra.choice(range(100))
my_coord = get_region(x,y)
if my_data.get(my_coord):
my_data[my_coord].append((x,y))
else:
my_data[my_coord]= [(x,y),]
print my_data

Generating all unique combinations for "drive ya nuts" puzzle

A while back I wrote a simple python program to brute-force the single solution for the drive ya nuts puzzle.
(source: tabbykat.com)
The puzzle consists of 7 hexagons with the numbers 1-6 on them, and all pieces must be aligned so that each number is adjacent to the same number on the next piece.
The puzzle has ~1.4G non-unique possibilities: you have 7! options to sort the pieces by order (for example, center=0, top=1, continuing in clockwise order...). After you sorted the pieces, you can rotate each piece in 6 ways (each piece is a hexagon), so you get 6**7 possible rotations for a given permutation of the 7 pieces. Totalling: 7!*(6**7)=~1.4G possibilities. The following python code generates these possible solutions:
def rotations(p):
for i in range(len(p)):
yield p[i:] + p[:i]
def permutations(l):
if len(l)<=1:
yield l
else:
for perm in permutations(l[1:]):
for i in range(len(perm)+1):
yield perm[:i] + l[0:1] + perm[i:]
def constructs(l):
for p in permutations(l):
for c in product(*(rotations(x) for x in p)):
yield c
However, note that the puzzle has only ~0.2G unique possible solutions, as you must divide the total number of possibilities by 6 since each possible solution is equivalent to 5 other solutions (simply rotate the entire puzzle by 1/6 a turn).
Is there a better way to generate only the unique possibilities for this puzzle?
To get only unique valid solutions, you can fix the orientation of the piece in the center. For example, you can assume that that the "1" on the piece in the center is always pointing "up".
If you're not already doing so, you can make your program much more efficient by checking for a valid solution after placing each piece. Once you've placed two pieces in an invalid way, you don't need to enumerate all of the other invalid combinations.
If there were no piece in the centre, this would be easy. Simply consider only the situations where piece 0 is at the top.
But we can extend that idea to the actual situation. You can consider only the situations where piece i is in the centre, and piece (i+1) % 7 is at the top.
I think the search space is quite small, though the programming might be awkward.
We have seven choices for the centre piece. Then we have 6 choices for the
piece above that but its orientation is fixed, as its bottom edge must match the top edge of the centre piece, and similarly whenever we choose a piece to go in a slot, the orientation is fixed.
There are fewer choices for the remaining pieces. Suppose for
example we had chosen the centre piece and top piece as in the picture; then the
top right piece must have (clockwise) consecutive edges (5,3) to match the pieces in
place, and only three of the pieces have such a pair of edges (and in fact we've already
chosen one of them as the centre piece).
One could first off build a table with a list
of pieces for each edge pair, and then for each of the 42 choices of centre and top
proceed clockwise, choosing only among the pieces that have the required pair of edges (to match the centre piece and the previously placed piece) and backtracking if there are no such pieces.
I reckon the most common pair of edges is (1,6) which occurs on 4 pieces, two other edge pairs ((6,5) and (5,3)) occur on 3 pieces, there are 9 edge pairs that occur on two pieces, 14
that occur on 1 piece and 4 that don't occur at all.
So a very pessimistic estimate of the number of choices we must make is
7*6*4*3*3*2 or 3024.

Categories

Resources