Tile placement algorithm - algorithm

I have this field of tiles which is 36 x 36 inches wide and high.
So I have blocks 8x8, 6x6, 6x8, 4x8 which can be rotated 90 degrees to fit wherever possible.
My task is to make application that calulates which and how many blocks should be chosen so that all together fit in to a given wall oppening. In this example oppening 36 x 36.
Note: The oppening should be filled with as least as possible tiles, meaning bigger tiles have priority
Which algorithm should I use for tile placement?
Another example. Field 30 x 30 is drawn like this:
50 x 50

Since amit gave the general case answer, I'll make this one specific. With those four blocks sizes, and assuming it's even possible (dimensions are even and >= 6, etc), you can use a semi-greedy algorithm:
The first obective is to maximize the number of 8x8 blocks. To do that, you need to figure out how many 6 size blocks you need in each direction. For each dimension, just check for divisibility by 8. If it's not divisible, subtract 6. Repeat until divisible (it shouldn't take more than 3 tries).
However many times it took, that's how may 6x6 blocks you need in that dimension. Form a rectangle out of them and put it in one corner. Form another rectangle out of 8x8 blocks and put them in the opposite corner. The corners of these two rectangles should be touching.
So now you probably have some leftover space, in the form of two rectangles in the opposite corners. We know that one dimension of each is divisible by 8, and one is divisible by 6. The easy way out here would be to fill it up with 6x8 blocks rotated appropriately, but that doesn't guarantee the maximum number of large(8x8) blocks. For example, with 50x50, you'd have two rectangles of 18x32 left. You could fill them with twelve 6x8 tiles each. You can't even do better than 12 blocks each, but you can fit more 8x8 blocks in there.
If that's not a concern, then you're done (hooray). The bonus this way is that you never need to use the 4x8 blocks.
If you do want to maximize the 8x8 blocks, you'll have to take another step. We're concentrating on the dimension divisible by 6 here, because the 8 is easy. Every size we might need(8x8,6x8,4x8) stacks there perfectly.
For the other side, there are only 3 possible numbers that it could be: 6, 12, and 18. If it's anything else, the first step wasn't done right. Then take the following action:
For 6, add a row of 6x8 (no optimization)
For 12, add a row of 4x8 and a row of 8x8
For 18, add a row of 4x8, a row of 6x8, a row of 8x8
Done!
To see the difference, here we have two 50x50 grids:
Blue - 8x8
Red - 6x6
Green - 6x8
Gray - 4x8
This first example gives us 49 total blocks. The blue is a 32x32 area (16 blocks), red is 18x18 (9 blocks), and the rest is simply filled with 6x8's (24 blocks).
This example still gives 49 total, but there are more 8x8 blocks. Here we have 24 large blocks, rather than 16 in the last example. There are now also 4x8 blocks being used.

Here you go, in Python:
def aux(x):
# in h we store the pre-calculated results for small dimensions
h = {18:[6,6,6], 16:[8,8], 14:[8,6], 12:[6,6], 10:[6,4], 8:[8], 6:[6], 4:[4]}
res = []
while x > 18:
# as long as the remaining space is large, we put there tiles of size 8
res.append(8)
x -= 8
if x not in h:
print("no solution found")
return []
return res + h[x]
def tiles( x, y ):
ax = aux(x) # split the x-dimension into tiles
ay = aux(y) # split the y-dimension into tiles
res = [ [ (x,y) for x in ax ] for y in ay ]
for u in res:
print(u)
return res
tiles( 30, 30 )
The basic idea is that you can solve x and y independently, and then combine the two solutions.
Edit: As Dukeling says this code happily uses 4x6 and 4x4 blocks, contrary to the requirements. However, I think it does that only if there is no other way. So if the results contains such blocks then there is no solution without those blocks. And if you have no Python readily available, you can play with this code here: http://ideone.com/HHB7F8 , just press fork right above the source code.

Assuming you are looking for general case answer, I am sorry to say - but this problem is NP-Complete. It is basically a 2D variation of the Subset Sum Problem.
The subset sum problem: Given a set S and a number x - find out if there is a subset of S that sums to x.
It is easy to see that by reducing the subset sum problem to a "field" of size 1*x and for every s in S we have a tile 1*s - a solution to one problem is also a solution to the other one.
Thus - there is no known polynomial solution to this problem, and most believe one does not exist.
Note however, there is a pseudo-polynomial dynamic programming solution to subset sum that might be utilized here as well.

Related

Tensorflow output from stride

While trying to use Tensorflow I encountered a little problem regarding the stride.
I have an image of size 67*67, and I want to apply a filter of size 7*7 with stride 3. The output layer should have an edge length of 20 calculated from:
Where n is the output layer edge length (in this case, 20). It is calculated in the follow way:
If we only consider the first row (since other rows are the same), then out of the 67 elements in the first row, the first 7 would go to the first cell of the output layer. Then the filter moves 3 element to the right, which makes the filter covering element 4 to 10, and that would correspond to the 2nd element of the output layer. So on so forth. Every time we advance 3 elements and the total number of times we will advance (counting the first step where it covers 7 elements) is n. Thus the equation I used.
However, the output layer I got from Tensorflow was 23, which is 67/3 and rounded up to the next integer. I don't understand the reasoning behind this.
Can someone explain why it is done like this in Tensorflow?
Thanks!
Output size is computed in two ways depending on the padding you are using. If you are using 'SAME' padding, the output size is computed as:
out_height = ceil(float(in_height) / float(strides[1]))
out_width = ceil(float(in_width) / float(strides[2]))
Where as with 'VALID' padding output is computed as:
out_height = ceil(float(in_height - filter_height + 1) / float(strides[1]))
out_width = ceil(float(in_width - filter_width + 1) / float(strides[2]))
Which is what you were using to calculate your output, but we can clearly see you must be using 'SAME' padding.
So in your case you get:
If you were actually using 'VALID' padding, the output would be closer to your approximation.
You can read more about how tensorflow calculates feature map sizes and padding here.

Averaging fft2s of resulting matrix from blockproc fft2 on 20x20 blocks of 40x100 image?

I am relatively new to matlab and image processing, so please bear with me.
What I am trying to do is characterize noise within an image, specifically by averaging the fft of an area where this noise occurs with high probability.
img = img(1:40,1:100)
imshow(img);
ffts = blockproc(img, [20 20], #(block_struct) fftshift(fft2(block_struct.data)));
// fft = imresize(ffts, [40 100], 'nearest');
Essentially, this code takes the upper left hand 40 x 100 portion of the image and then performs a block-process on each 20 x 20 subsection of that area calculating fft2. Hopefully, my logic sounds alright so far.
What I am wondering though, is if there is any way to perform the average fft2 of the 20 x 20 subsections of the 40 x 100 fft matrix with the built-in matlab functionality. I know that this could be completed relatively easy with loops, but I'd like to keep the solution in my code as compact as possible.
I've read through the manual a little and it is apparent that there are a couple of matlab functions that may perform this; However, I am not entirely confident in my application so far. Any directions are welcomed!
This can easily be done in 3 lines of code.
Line #1
First use im2col to reshape each distinct block neighbourhood of 20 x 20 into a single column. As such, the output of this will be a 400 x N matrix, where each column denotes a unique block neighbourhood that has been reshaped into a column. Each column will have 400 rows, as each neighbourhood has 400 elements (20 x 20). N would be the total number of unique blocks we have in your 40 x 100 image. This would amount to 10, as we can fit 2 blocks horizontally and 5 blocks vertically given the 20 x 20 requirement.
Line #2
What is great about the output of im2col is that the ith row of im2col tells you the ith element for every block in your image. As such, all you have to do next is take each row and average over all of the columns. The output will be a 400 x 1 vector that denotes your average FFT for all of the blocks. This can be achieved using mean and specifying that we want to average over the second dimension (second parameter is 2), which is the columns.
Line #3
We then need to reshape this back into a 20 x 20 matrix, so use reshape to do this. We specify that the output matrix is 20 x 20, given the 400 x 1 element vector.
One question that you may ask is whether or not this re-ordering is guaranteed to reorder our FFT block correctly. This is guaranteed because when im2col constructed each block into a column, it progresses in a column-major order. This means that for one column of blocks, we construct them on a row-by-row basis. Once we get our 20 x 20 set of distinct blocks, these blocks are arranged so that the are sampled in column major order. This means that a single 20 x 20 block gets constructed into a 400 x 1 column vector, where columns of the 20 x 20 block are stacked on top of each other from left to right. Therefore, by doing mean and reshape, the spatial locations for each block do correspond to each other and will thus produce the right answer.
Without further ado, here's the code:
colBlocks = im2col(ffts, [20 20], 'distinct'); %// Line 1
meanCol = mean(colBlocks, 2); %// Line 2
fftBlockAverage = reshape(meanCol, [20 20]); %// Line 3
Minor Side Effect
Because the FFT is complex valued in nature, by doing the average, you would average the real and imaginary components separately. This is how MATLAB handles the average of complex valued data. I'm not sure what analysis you'll be performing after you calculate the average 2D FFT block, but bear this in mind before you proceed any further with your analysis.
Sidenote
Divakar in an earlier answer created a more efficient implementation of im2col. This is especially useful if you don't have the Image Processing Toolbox installed. You can check out that implementation here. It has been shown that the timing between this function and MATLAB's im2col are magnitudes faster.
Benchmarking
As a bonus, here is a benchmark using his code. Timing results were taken using a 40 x 100 matrix where the im2col built-in function was timed, and Divakar's custom function after. Results show that his method is faster. This may be very useful when considering larger size images. However, if you are looking for succinctness, use what I have written. If you want something fast, use his method.
Benchmarking Code
%// Input Parameters
nrows = 20;
ncols = 20;
A = rand(40,100);
disp('------------------------- With IM2COL');
tic
B1 = im2col(A,[nrows ncols],'distinct');
toc,clear B1
disp('----------------- With CUSTOM-BUILT IM2COL');
tic
B2 = im2col_distinct(A,[nrows ncols]);
toc,clear B2
Results
------------------------- With IM2COL
Elapsed time is 0.026914 seconds.
----------------- With CUSTOM-BUILT IM2COL
Elapsed time is 0.004186 seconds.

Labelling a grid using n labels, where every label neighbours every other label

I am trying to create a grid with n separate labels, where each cell is labelled with one of the n labels such that all labels neighbour (edge-wise) all other labels somewhere in the grid (I don't care where). Labels are free to appear as many times as necessary, and I'd like the grid to be as small as possible. As an example, here's a grid for five labels, 1 to 5:
3 2 4
5 1 3
2 4 5
While generating this by hand is not too bad for small numbers of labels, it appears to be very hard to generate a grid of reasonable size for larger numbers and so I'm looking to write a program to generate them, without having to resort to a brute-force search. I imagine this must have been investigated before, but the closest I've found are De Bruijn tori, which are not quite what I'm looking for. Any help would be appreciated.
EDIT: Thanks to Benawii for the following improved description:
"Given an integer n, generate the smallest possible matrix where for every pair (x,y) where x≠y and x,y ∈ {1,...,n} there exists a pair of adjacent cells in the matrix whose values are x and y."
You can experiment with a simple greedy algorithm.
I don't think that I'm able to give you a strict mathematical prove, at least because the question is not strictly defined, but the algorithm is quite intuitive.
First, if you have 1...K numbers (K labels) then you need at least K*(K-1)/2 adjacent cells (connections) for full coverage. A matrix of size NxM generates (N-1)*M+(M-1)*N=2*N*M-(N+M) connections.
Since you didn't mention what you understand under 'smallest matrix', let's assume that you meant the area. In that case it is obvious that for the given area the square matrix will generate bigger number of connections because it has more 'inner' cells adjacent to 4 others. For example, for area 16 the matrix 4x4 is better than 2x8. 'Better' is intuitive - more connections and more chances to reach the goal. So lets use target square matrixes and expand them if needed. The above formula will become 2*N*(N-1).
Then we can experiment with the following greedy algorithm:
For input number K find the N such that 2*N*(N-1)>K*(K-1)/2. A simple school equation.
Keep an adjacency matrix M, set M[i][i]=1 for all i, and 0 for the rest of the pairs.
Initialize a resulting matrix R of size NxN, fill with 'empty value' markers, for example with -1.
Start from top-left corner and iterate right-down:
for (int i = 0; i < N; ++i)
for (int j = 0; j < N; ++j)
R[i][j];
for each such R[i][j] (which is -1 now) find such a value which will 'fit best'. Again, 'fit best' is an intuitive definition, here we understand such a value that will contribute to a new unused connection. For that reason create the set of already filled cell neighbor numbers - S, its size is 2 at most (upper and left neighbor). Then find first k such that M[x][k]=0 for both numbers x in S. If no such number then try at least one new connection, if no number even for one then both neighbors are completely covered, put some number from uncovered here - probably the one in 'worst situation' - such x where Sum(M[x][i]) is the smallest. You should also choose the one in 'worst situation' when there are several ones to choose from in any case.
After setting the value for R[i][j] don't forget to mark the new connections with numbers x from S - M[R[i][j]][x] = M[x][R[i][j]] = 1.
If the matrix is filled and there are still unmarked connections in M then append another row to the matrix and continue. If all the connections are found before the end then remove extra rows.
You can check this algorithm and see what will happen. Step 5 is the place for playing around, particularly in guessing which one to choose in equal situation (several numbers can be in equally 'worst situation').
Example:
for K=6 we need 15 connections:
N=4, we need 4x4 square matrix. The theory says that 4x3 matrix has 17 connections, so it can possibly fit, but we will try 4x4.
Here is the output of the algorithm above:
1234
5615
2413
36**
I'm not sure if you can do by 4x3, maybe yes... :)

Looking for an algorithm (version of 2-dimensional binary search)

Easy problem and known algorithm:
I have a big array with 100 members. First X members are 0, and the rest are 1. Find X.
I am solving it by a binary search: Check member 50, if it is 0 - check member 75, etc, until I find adjacent 0 and 1.
I am looking for an optimized algorithm for the same problem in 2-dimensions:
I have 2-dimensional array 100*100. Those members that are on rows 0-X AND on columns 0-Y are 0, and the rest are 1. How to find Y and X?
Edit : The optimal solution consists in two simple binary search.
I'm very sorry for the long and convoluted post I did below. What the problem fundamentally consists in is to find a point in a space that contains 100*100 elements. The best you can do is to divide at each step this space in two. You can do it in a convoluted way (the one I did in the rest of the post) But if you realize that a binary search on the X axis still divides the research space in two at each step, (the same goes for the Y axis) then you understand that it's optimal.
I still let the thing I did, and I'm sorry that I made some peremptory affirmations in it.
If you're looking for a simple algorithm (though not optimal) just run the binary search twice as suggested.
However, if you want an optimal algorithm, you can look for the boundary on X and on Y at the same time. (You have to note that the two algorithm have same asymptotical complexity, but the optimal algorithm will still be faster)
In all the following graphics, the point (0, 0) is in the bottom left corner.
Basically when you choose a point and get the result, you cut your space in two parts. When you think about it that is actually the biggest amount of information you can extract from this.
If you choose the point (the black cross) and the result is 1 (red lines), this means that the point you're looking for can not be in the gray space (thus must be in the remaining white area)
On the other hand, if the value is 0 (blue lines), this means that the point you're looking for can not be in the gray area (thus must be in the remaining white area)
So, if you get one 0 result and one 1 result, this is what you'll get :
The point you're looking for is either in rectangle 1, 2 or 3. You just need to check the two corners of rectangle 3 to know which of the 3 rectangle is the good one.
So the algorithm is the following :
Note where are the bottom left and top right corner of the rectangle you're working with.
Do a binary search along the diagonal of the rectangle until you've stumbled at least once on a 1 result and once a 0 result.
Check the 2 other corners of the rectangle 3 (you'll necessary already know the values of the two corners on the diagonal) It is possible to check only one corner to know the right rectangle (but you'll have to check the two corners if the right rectangle is the rectangle 3)
Determine if the point you're looking for is in rectangle 1, 2 or 3
Repeat by reducing the problem to the good rectangle until the final rectangle is reduced to a point : it's the value you're looking for
Edit : if you want the supremum optimality, you'd not the when you choose the point (50, 50), you do not cut the space in equal part. One is three time bigger than the other. Ideally, you'll choose a point that cuts the space in two equal regions (area-wise)
You should compute once at the beginning the value of factor = (1.0 - 1.0/sqrt(2.0)). Then when you want to cut bewteen values a and b, choose the cutting point as a + factor*(b-a). When you cut the initial 100x100 rectangle at the point (100*factor, 100*factor) the two regions will have an area (100*100)/2, thus the convergence will be quicker.
Run your binary search twice. First determine X by running binary search on the last row and then determine Y by running binary search on last column.
Simple solution: go first in X-direction and then in Y-direction.
Check (0,50); If it is 0, check (0,75); until You find adjacent 0 and 1. Then go to Y direction from there.
Second solution:
Check member (50,50). If it is 1, check (25,25), until You find 0. Continue, until You find adjacent (X,X) and (X+1,X+1) that are 0 and 1. Then test (X,X+1) and (X+1,X). Neither or one of them will be 1. If neither, You are finished. If only one, say for example (X+1,X), then You know that the box's size is between (X+1,X) and (100,X). Use binary search to find box's height.
EDIT: As Chris pointed out, it seems that the simple approach is faster.
Second solution (modified):
Check member (50,50). If it is 1, check (25,25), until You find 0. Continue, until You find adjacent (X,X) and (X+1,X+1) that are 0 and 1. Then test (X,X+1). If it is 1, then do binary search on line (X,X+1)...(X,100). Else do binary search on line (X,X)...(100,X).
Even then I am probably beating a dead horse here. If it will be faster, then by neglible amount. This is just for theoretical fun. :)
EDIT 2 As Fezvez and Chris put it, binary search divides the search space in two most efficiently; My approach divides the area to 1/4 and 3/4 pieces. Fezvez pointed out that this could be remedied by calculating the dividing factor beforehand (but that would be extra calculation). In modified version of my algorithm I choose the direction where to go (X or Y direction), which effectively also divides the search space in two, and then conduct binary search. To conclude, this shows that this approach will always be a bit slower. (and more complicated to implement.)
Thank You, Igor Oks, for interesting question. :)
Use binary search on both dimensions and the 1D case:
Start with j=50. Now the 1-D array obtained by varying i is of the desired form - so find X from 1D case.
If X = 100 (i.e. no ones), then make j=75 (middle of the range in j dimension) and repeat.
If X < 100, then you have found it. All that is left is to fix i=X and find Y from the 1D case.

plane bombing problems- help

I'm training code problems, and on this one I am having problems to solve it, can you give me some tips how to solve it please.
The problem is taken from here:
https://www.ieee.org/documents/IEEEXtreme2008_Competitition_book_2.pdf
Problem 12: Cynical Times.
The problem is something like this (but do refer to above link of the source problem, it has a diagram!):
Your task is to find the sequence of points on the map that the bomber is expected to travel such that it hits all vital links. A link from A to B is vital when its absence isolates completely A from B. In other words, the only way to go from A to B (or vice versa) is via that link.
Due to enemy counter-attack, the plane may have to retreat at any moment, so the plane should follow, at each moment, to the closest vital link possible, even if in the end the total distance grows larger.
Given all coordinates (the initial position of the plane and the nodes in the map) and the range R, you have to determine the sequence of positions in which the plane has to drop bombs.
This sequence should start (takeoff) and finish (landing) at the initial position. Except for the start and finish, all the other positions have to fall exactly in a segment of the map (i.e. it should correspond to a point in a non-hit vital link segment).
The coordinate system used will be UTM (Universal Transverse Mercator) northing and easting, which basically corresponds to a Euclidian perspective of the world (X=Easting; Y=Northing).
Input
Each input file will start with three floating point numbers indicating the X0 and Y0 coordinates of the airport and the range R. The second line contains an integer, N, indicating the number of nodes in the road network graph. Then, the next N (<10000) lines will each contain a pair of floating point numbers indicating the Xi and Yi coordinates (1 < i<=N). Notice that the index i becomes the identifier of each node. Finally, the last block starts with an integer M, indicating the number of links. Then the next M (<10000) lines will each have two integers, Ak and Bk (1 < Ak,Bk <=N; 0 < k < M) that correspond to the identifiers of the points that are linked together.
No two links will ever cross with each other.
Output
The program will print the sequence of coordinates (pairs of floating point numbers with exactly one decimal place), each one at a line, in the order that the plane should visit (starting and ending in the airport).
Sample input 1
102.3 553.9 0.2
14
342.2 832.5
596.2 638.5
479.7 991.3
720.4 874.8
744.3 1284.1
1294.6 924.2
1467.5 659.6
1802.6 659.6
1686.2 860.7
1548.6 1111.2
1834.4 1054.8
564.4 1442.8
850.1 1460.5
1294.6 1485.1
17
1 2
1 3
2 4
3 4
4 5
4 6
6 7
7 8
8 9
8 10
9 10
10 11
6 11
5 12
5 13
12 13
13 14
Sample output 1
102.3 553.9
720.4 874.8
850.1 1460.5
102.3 553.9
Pre-process the input first, so you identify the choke points. Algorithms like Floyd-Warshall would help you.
Model the problem as a Heuristic Search problem, you can compute a MST which covers all choke-points and take the sum of the costs of the edges as a heuristic.
As the commenters said, try to make concrete questions, either here or to the TA supervising your class.
Don't forget to mention where you got these hints.
The problem can be broken down into two parts.
1) Find the vital links.
These are nothing but the Bridges in the graph described. See the wiki page (linked to in the previous sentence), it mentions an algorithm by Tarjan to find the bridges.
2) Once you have the vital links, you need to find the smallest number of points which given the radius of the bomb, will cover the links. For this, for each link, you create a region around it, where dropping the bomb will destroy it. Now you form a graph of these regions (two regions are adjacent if they intersect). You probably need to find a minimum clique partition in this graph.
Haven't thought it through (especially part 2), but hope it helps.
And good luck in the contest!
I think Moron' is right about the first part, but on the second part...
The problem description does not tell anything about "smallest number of points". It tells that the plane flies to the closest vital link.
So, I think the part 2 will be much simpler:
Find the closest non-hit segment to the current location.
Travel to the closest point on the closest segment.
Bomb the current location (remove all segments intersecting a circle)
Repeat until there are no non-hit vital links left.
This straight-forward algorithm has a complexity of O(N*N), but this should be sufficient considering input constraints.

Resources