Algorithm to count unit triangles in large composite shape - python

I need to write a brute-force algorithm to count the number of unit triangles in a complex shape. The shape is created each iteration by adding triangles to surround all outer edges.
The shape in iteration number n would look as above and the outputs would be 1 4 10 respectively.
Unfortunately I do not really know where to begin, first thought was to create 2 classes; a triangle and a grid class consisting of multiple triangles. However adding the outer triangles would prove difficult to do past n = 3 as some edge pairs will only need 1 shared unit triangle.
Any thoughts?

Nevermind solution was simpler than I ever imagined as triangles added increase by 3 every time a simple for loop to add from n=1 worked easily enough.

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.

Suppose an array contains only two kinds of elements, how to quickly find their boundaries?

I've asked a similar question before, but this time it's different.
Since our array contains only two elements, we might as well set it to 1 and -1, where 1 is on the left side of the array and -1 is on the right side of the array:
[1,...,1,1,-1,-1,...,-1]
Both 1 and -1 exist at the same time and the number of 1 and -1 is not necessarily the same. Also, the numbers of 1 and -1 are both very large.
Then, define the boundary between 1 and -1 as the index of the -1 closest to 1. For example, for the following array:
[1,1,1,-1,-1,-1,-1]
Its boundary is 3.
Now, for each number in the array, I cover it with a device that you have to unlock to see the number in it.
I want to try to unlock as few devices as possible that cover 1, because it takes much longer to see a '1' than it takes to see a '-1'. And I also want to reduce my time cost as much as possible.
How can I search to get the boundary as quickly as possible?
The problem is very like the "egg dropping" problem, but where a wrong guess has a large fixed cost (100), and a good guess has a small cost (1).
Let E(n) be the (optimal) expected cost of finding the index of the right-most 1 in an array (or finding that the array is all -1), assuming each possible position of the boundary is equally likely. Define the index of the right-most 1 to be -1 if the array is all -1.
If you choose to look at the array element at index i, then it's -1 with probability i/(n+1), and 1 with probability (n-i+1)/(n+1).
So if you look at array element i, your expected cost for finding the boundary is (1+E(i)) * i/(n+1) + (100+E(n-i-1)) * (n-i+1)/(n+1).
Thus E(n) = min((1+E(i)) * i/(n+1) + (100+E(n-i-1)) * (n-i+1)/(n+1), i=0..n-1)
For each n, the i that minimizes the equation is the optimal array element to look at for an array of that length.
I don't think you can solve these equations analytically, but you can solve them with dynamic programming in O(n^2) time.
The solution is going to look like a very skewed binary search for large n. For smaller n, it'll be skewed so much that it will be a traversal from the right.
If I am right, a strategy to minimize the expectation of the cost is to draw at a fraction of the interval that favors the -1 outcome, in inverse proportion of the cost. So instead of picking the middle index, take the right centile.
But this still corresponds to a logarithmic asymptotic complexity.
There is probably nothing that you can do regarding the worst case.

Is there a more efficient algorithm to calculate the Manhattan distance of a 8-puzzle game?

I'm currently writing an algorithm that solves the 8-puzzle game through an A* search algorithm with Python. However, when I time my code, I find that get_manhattan_distance takes a really long amount of time.
I ran my code with cProfile for Python, and the results are below what is printed out by the program. Here is a gist for my issue.
I've already made my program more efficient by copying using Numpy Arrays instead of Python's lists. I don't quite know how to make this step more efficient. My current code for get_manhattan_distance is
def get_manhattan(self):
"""Returns the Manhattan heuristic for this board
Will attempt to use the cached Manhattan value for speed, but if it hasn't
already been calculated, then it will need to calculate it (which is
extremely costly!).
"""
if self.cached_manhattan != -1:
return self.cached_manhattan
# Set the value to zero, so we can add elements based off them being out of
# place.
self.cached_manhattan = 0
for r in range(self.get_dimension()):
for c in range(self.get_dimension()):
if self.board[r][c] != 0:
num = self.board[r][c]
# Solves for what row and column this number should be in.
correct_row, correct_col = np.divmod(num - 1, self.get_dimension())
# Adds the Manhattan distance from its current position to its correct
# position.
manhattan_dist = abs(correct_col - c) + abs(correct_row - r)
self.cached_manhattan += manhattan_dist
return self.cached_manhattan
The idea behind this is, the goal puzzle for a 3x3 grid is the following:
1 2 3
4 5 6
7 8
Where there is a blank tile (the blank tile is represented by a 0 in the int array). So, if we have the puzzle:
3 2 1
4 6 5
7 8
It should have a Manhattan distance of 6. This is because, 3 is two places away from where it should be. 1 is two places away from where it should be. 5 is one place away from where it should be, and 6 is one place away from where it should be. Hence, 2 + 2 + 1 + 1 = 6.
Unfortunately, this calculation takes a very long time because there are hundreds of thousands of different boards. Is there any way to speed this calculation up?
It looks to me like you should only need to calculate the full Manhattan distance sum for an entire board once - for the first board. After that, you're creating new Board entities from existing ones by swapping two adjacent numbers. The total Manhattan distance on the new board will differ only by the sum of changes in Manhattan distance for these two numbers.
If one of the numbers is the blank (0), then the total distance changes by minus one or one depending on whether the non-blank number moved closer to its proper place or farther from it. If both of the numbers are non-blank, as when you're making "twins", the total distance changes by minus two, zero, or two.
Here's what I would do: add a manhattan_distance = None argument to Board.__init__. If this is not given, calculate the board's total Manhattan distance; otherwise simply store the given distance. Create your first board without this argument. When you create a new board from an existing one, calculate the change in the total distance and pass the result in to the new board. (The cached_manhattan becomes irrelevant.)
This should reduce the total number of calculations involved with distance by quite a bit - I'd expect it to speed things up by several times, more the larger your board size.

Vectorize Conway's Game of Life in pure numpy?

I'm wondering if there is a way to implement Conway's game of life without resorting to for loops, if statements and other control structures typical of programming.
It should be pretty easy to vectorize for loops, but how would you convert the checks on the neighborhood to a matrix operation?
The base logic is something like this:
def neighbors(cell, distance=1):
"""Return the neighbors of cell."""
x, y = cell
r = xrange(0 - distance, 1 + distance)
return ((x + i, y + j) # new cell offset from center
for i in r for j in r # iterate over range in 2d
if not i == j == 0) # exclude the center cell
I hope this is not considered as off-topic by the mods, I'm genuinely curios and I am just starting out with CAs.
Cheers
The answer to your question is "yes, it is possible" (particularly the board updates from board n to board n+1).
I describe the process in detail here. The main technique to generate the neighborhood around a central cell involves using "strides" (the way that numpy and other array computation systems know how to walk across rows and columns of elements when they are really stored in memory in flat 1D thing) in a custom fashion to generate neighborhoods around cells. I describe that process here.
One last comment: since Game of Life iterates from state n to state n+1, while you could literally remove all imperative looping, it doesn't really make sense to take out that top-level control loop. So, has a loop: for round in range(num_rounds): board.update() where board.update doesn't use loops (except to do some side calculations ... again, you could remove those but it would make the program longer and less elegant).
To give you a concrete example (and be more compatible with StackOverflow's answer requirements), here's some select cutting and pasting from my posts to generate the central neighborhoods from a simple 4x4 board [apologies, this is python 2 code, you'll have to modify the prints a bit]:
board = np.arange(16).reshape((4,4))
print board
print board.shape
We want to pick out the four "complete" neighborhoods centered around 5, 6, 7, and 8. Let’s look at the neighborhood for 5. What is the shape of the result? 3×3. What are the strides? Well, to walk across a row is still just walking one element at a time and to get to the next row is still 4 elements at a time. These are the same as the strides in the original. The difference is we don’t take "everything", we just take a selection. Let’s see if that actually works:
from numpy.lib.stride_tricks import as_strided
neighbors = as_strided(board, shape=(3,3), strides=board.strides)
print neighbors
Ok, nice. Now, if we want all four neighborhoods, what is the output shape? We have several 3×3 results. How many? In this case, we have 2×2 of them (for each of the "center" cells). This gives a shape of (2,2,3,3) – the neighborhoods are the inner dimensions and the organization of the neighborhoods is the outer dimensions.
So, our strides (in terms of elements) end up being (4,0) within one neighborhood and (4,0) for progressing neighborhood to neighborhood. The total stride (element wise) is: (4,0,4,0). But, the component strides (our outer two dimensions) are the same as the strides of the board. This means that our neighborhood strides are board.strides + board.strides.
print board.strides + board.strides
neighborhoods = as_strided(board,
shape=(2,2,3,3),
strides=board.strides+board.strides)
print neighborhoods[0,0]
print neighborhoods[-1, -1]

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