I'd like to generate the adjacency matrix for a boggle board. A boggle board is one where you have alphabets in a nxn matrix like this:
http://www.wordtwist.org/sample.gif
Each cell is connected to its neighbor cell; basically we move up/down/left/right/diagonally to connect to another cell.
If each cell is viewed as a vertex in a graph, then we can find the adjacency matrix of the boggle board.
I came up with the following formulas to find the adjacent cells:
Assume the index of the cells start with 0 and are numbered from left to right.
i = cell index, n = number of rows/columns. So in a 3x3 matrix, i=0 would be the first cell and n is 3.
up = i-n
down = i+n
left = i-1
right = i+1
diagonal 1 = i-(n+1), i+(n+1)
diagonal 2 = i-(n-1), i+(n-1)
The above formulas fail in case of corner cells. How to exclude the invalid cells for corner cases?
You shouldn't have to "exclude" anything, merely check your result to see whether it is in bounds or not, if it isn't then there is no valid cell. (i.e. If you are at the top left of your 3x3 matrix (i = 0) then up (i - n) is (0 - 3 = -3). Since -3 is outside the bounds of your matrix, there is no valid cell.
So if you are doing a search and want to travel along the "up" adjacent cell, first check whether that location is in bounds, if it is not then you are at the end.
To check if you are on the left or right edge of the matrix, use:
if i % (n-1) == 0 // Right edge
if i % (n) == 0 // Left edge
Related
What would be an efficent way to solve the following problem?
Given an NxN matrix of natural numbers, return ALL positions (matrix indexes, i and j) whose number is bigger than all their adjacent positions (horizontal and vertical only, if position is out of the matrix it counts as -1).
In other words, matrix[i][j] has to be bigger than all of the following:
matrix[i+1][j], matrix[i-1][j], matrix[i][j+1], matrix[i][j-1]
If matrix[i][j] fulfilled the condition then (i,j) is a valid position.
Is there any way to solve this without checking every single cell and making all 4 comparisons?
I have an array of points, and my goal is to pick two so that I maximize the area of the rectangle formed by the two points (one representing the low left corner and the other one the right top corner).
I could do this in O(n^2) by just doing two for loops and calculating every single possible area, but I think there must be a more efficient solution:
max_area = 0
for p1 in points:
for p2 in points:
area = p2[0]p2[1] + p1[0]p1[1] - p2[1]p1[0] - p2[0]p1[1]
if area > max_area:
max_area = area
It's clear that I want to maximize the area of the second point with the origin (0,0) (so p2[0]p2[1]), but I'm not sure how to go forward with that.
Yes, there's an O(n log n)-time algorithm (that should be matched by an element distinctness lower bound).
It suffices to find, for each p1, the p2 with which it has the largest rectangular area, then return the overall largest. This can be expressed as a 3D extreme point problem: each p2 gives rise to a 3D point (p2[0], p2[1], p2[0] p2[1]), and each p1 gives rise to a 3D vector (-p1[0], -p1[1], 1), and we want to maximize the dot product (technically plus p1[0] p1[1], but this constant offset doesn't affect the answer). Then we "just" have to follow Kirkpatrick's 1983 construction.
Say you have a rectangle formed by four points: A (top left), B (top right), C (bottom right) and D (bottom left).
The idea is to find two points p1 and p2 that are the closest to B and D respectively. This means that p1 and p2 are the furthest possible from each other.
def nearest_point(origin, points):
nearest = None
mindist = dist(origin, points[0])
for p in points[1:]:
d = dist(origin, p)
if mindist > d:
mindist = d
nearest = p
return nearest
Call it for B and D as origins:
points = [...]
p1 = nearest_point(B, points) # one for loop
p2 = nearest_point(D, points) # one for loop
Note that there can be multiples closest points which are equally distant from the origin (B or D). In this case, nearest_point() should return an array of points. You have to do two nested for loops to find the furthest two points.
Divide and conquer.
Note: This algorithm presumes that the rectangle is axis-aligned.
Step 1: Bucket the points into a grid of 4x4 buckets. Some buckets
may get empty.
Step 2: Using the corners of the buckets, calculate
maximum areas by opposite corners between not empty buckets. This may result in
several pairs of buckets, because your work with corners, not points. Notice also that you use left corners for left buckets, and so for bottom, right, top corners for those b,r,t buckets. That's why an even number is used for the size of the grid.
Step 3: Re-bucket each bucket selected in step 2 as a new, smaller, 4x4 grid.
Repeat steps 2 & 3 until you get only a pair of buckets that contain only a point in each bucket.
I have not calculated the complexity of this algorithm. Seems O(n log(n)).
Consider a game where the game board is a grid with n rows and m columns. You begin at the bottom left corner of the grid (assume this has coordinates (0,0)). You start with a score of 0, and inventory space I > 0.
At each cell of the grid there may be one of two things, the cell is either empty, or contains some loot. Loot has a size x and value v, you can think of each potential piece of loot being indexed by the cell, i.e. L(i,j) = (x(i,j), v(i,j)), where L(i,j) = (0, 0) if the cell is empty.
From cell (i, j) the player can move up 1 row to one of three cells, (i + 1, j − 1), (i + 1, j), or (i + 1, j + 1). The player cannot move back down the rows or move side to side. When the player reaches a cell with loot they can either choose to take it or leave it. Taking it the loot decreases the players inventory space by the size x, while increasing their score by the value v.
How would a dynamic programming algorithm apply to this?
I figure that the subproblems would be moving up the row, where as long as there is a row above, and one of the left/right each. It would choose whichever one has the highest value v and fits in our inventory x, otherwise it just leaves it.
Input:
Table T of length N (N <= 10000) containing 32-bit integers. Each integer denotes length and direction of consecutive edge of polygon on a square grid (every vertex has integer coordinates). If integer is positive, it means edge goes up or right. If integer is negative, edge goes down or left. Edges are perpendicular to its neighbors. Edges do not intersect nor overlap with each other. Vertices do not overlap with each other.
Examplary input T:
2, -3, -1, 1, -1, 2
Represents two polygons (it doesn't matter which one we will choose):
Arrows denote
first edge corresponding to the first 2 in T.
Output:
Integer denoting surface area of given polygon. For exemplary input, the output should be 5.
Desired time complexity: O(N)
Desired memory complexity (not counting input): O(1)
Can you present such algorithm and rationale behind it?
Algorithm:
int area(int[] T) {
int area = 0;
int x = 0;
for (int i = 0; i < T.length; i += 2) {
x += t[i];
area += x * t[i + 1];
}
return Math.abs(area);
}
Description:
Our polygon is closed in a big rectangle. Based on this we are counting areas of small rectangles which are building our shape - rectangles which are inside polygon as well as rectangles which are outside (with opposite sign).
It doesn't matter from which vertex in polygon we are starting.
In the beginning we need one based line from which we will count vertical (it can be horizontal as well, it doesn't matter) translation of vertices.
We are getting the first number - it will tell us, how much from the based line our first vertex is moved. The second number is translation according to second coordinate. By multiplying this pair we are getting the first rectangle in our sum.
Second rectangle is described by third and fourth point:
the third number added to the first number is a vertical translation of the vertex
the fourth number is a horizontal translation of the vertex.
Multiplying this points is giving us the second rectangle.
We are continuing to do this for the rest of numbers in table. We are adding areas of rectangles. The result is an absolute value of the sum.
Given a 15*15 symmetric matrix, each row containing all the numbers from 1 to 15 and each column containing all the numbers from 1 to 15, how do you go on to prove that all the diagonal elements will be different?
I tried to prove that no two diagonal elements will be same, but couldn't come up with anything solid. Even tried it for 5*5 matrix, but nothing I could come up with to prove it.
Any help would be appreciated!
This is a problem of symmetric latin squares. The first observation (which requires a short proof) is that each of the numbers 1 to 15 occur an even number of times in the off-diagonal positions. Since 15 is odd, this means that each number must occur at least once in the diagonal positions. But there are only 15 diagonal positions and so each number must occur exactly once in the diagonal positions.
If by 'prove' you mean demonstrate for a particular matrix, see below. If by 'prove' you mean mathematically prove, well, all diagonal matrices are symmetric matrices, and a diagonal matrix isn't required to have unique elements, so not all symmetric matrices have unique elements on the diagonal.
One way to test a particular matrix is to make a new array containing all the diagonal elements, then eliminate duplicates in that array, and test the length. Another is to take each diagonal element and compare it against those elements on the diagonal with a higher index. Here's the latter with some pseudocode using 0 based arrays
unique = TRUE
for i = 0 to 14 {
value = matrix[i][i]
for j = i+1 to 14 // doesn't loop if i+1 > 14
if (value == matrix[j][j])
unique = FALSE
}
ADDED: The OP points out I missed the restriction on the contents of each row and column! All symmetric NxN matrices consisting of N unique values with no duplicated values in each row and column must have an antidiagonal consisting of only one value, by the definition of symmetry. If N is odd, the resulting matrix has a single element that is in both the diagonal and antidiagonal (and of course, if N is even, no element is in common). Given this, you can see the diagonal values must differ in each position from the antidiagonal, except in the common element. Combine that with the requirement that each row and each column has N values, and you'll see that the diagonal element must be different for each row. This isn't formal, but I hope it helps.
We can assume the given matrix is m * m, and we should fill the matrix with m distinct numbers: N1, N2 ... Nm.
Because each element should show up in each column/row once, for each number, it will show up n) times in the matrix.
Because it is symmetric, each number will show up x (even) times in the upper section above the diagonal or x (even) times in the lower section below the diagonal. In this way, in addition to the diagonal, each number will show up 2 * x (x is even) times in the matrix.
Therefore, if the given m is odd, each number should show up one more time in the diagonal; if the given is even, we don't require each number show up on the diagonal cause 2 * x is already even.