Given an m x n integer grid, return the size (i.e., the side length k) of the largest magic square that can be found within this grid.
The question can be found here on leetcode
I first wanted to see if a naive brute force approach would pass, so I came up with the following algorithm
Iterate through all values of k (from min(rows,cols) of the matrix to 1)
For each of the k values, check if it's possible to create a magic of square of dimensions kxk by checking all possible sub matrices and
return k if it's possible. This would be O(rows*cols*k^2)
So that would make the overall complexity O(k^3*rows*cols). (Please correct me if I am wrong)
I have attached my code in C++ below
class Solution {
public:
int largestMagicSquare(vector<vector<int>>& grid) {
int rows = grid.size(),cols = grid[0].size();
for(int k = min(rows,cols); k >= 2; k--){ // iterate over all values of k
for(int i = 0; i < rows-k+1; i++){
for(int j = 0; j < cols-k+1; j++){
int startX = i, startY = j, endX = i+k-1, endY = j+k-1;
int diagSum = 0, antiDiagSum = 0;
bool valid = true;
// calculate sum of diag
for(int count = 0; count < k; count++){
diagSum += grid[startX][startY];
startX++,startY++;
}
// this is the sum that must be same across all rows, cols, diag and antidiag
int sum = diagSum;
// calculate sum of antidiag
for(int count = 0; count < k; count++){
antiDiagSum += grid[endX][endY];
endX--,endY--;
}
if(antiDiagSum != sum) continue;
// calculate sum across cols
for(int r = i; r <=i+k-1; r++){
int colSum = 0;
for(int c = j; c <= j+k-1; c++){
colSum += grid[r][c];
}
if(colSum != sum){
valid = false;
break;
}
}
if(!valid) continue;
// calculate sum across rows
for(int c = j; c <= j+k-1; c++){
int rowSum = 0;
for(int r = i; r <= i+k-1; r++){
rowSum += grid[r][c];
}
if(rowSum != sum){
valid = false;
break;
}
}
if(!valid) continue;
return k;
}
}
}
return 1;
}
};
I thought I would optimize the solution once this works (Maybe binary search over the values of k). However, my code is failing for a really large test case for a matrix of dimension 50x50 after passing 74/80 test cases on Leetcode.
I tried to find out the source(s) that could be causing it to fail, but I am not really sure where the error is.
Any help would be appreciated. Thanks!
Please do let me know if further clarification about the code is needed
The calculation of antiDiagSum is wrong: it actually sums the values on the same diagonal as diagSum, just in reverse order. To traverse the opposite diagonal, you need to increment the Y coordinate and decrement the X coordinate (or vice versa), but your code decrements both of them.
It is probably easiest if you fix this by calculating both diagonal sums in the same loop:
for(int count = 0; count < k; count++){
diagSum += grid[startX][startY];
antiDiagSum += grid[endX][startY];
startX++, startY++, endX--;
}
Related
I'm trying to implement a quick program to solve a system of linear equations. The program reads the input from a file and then writes the upper-triangular system and solutions to a file. It is working with no pivoting, but when I try to implement the pivoting it produces incorrect results.
As example input, here is the following system of equations:
w+2x-3y+4z=12
2w+2x-2y+3z=10
x+y=-1
w-x+y-2z=-4
I expect the results to be w=1, x=0, y=-1 and z=2. When I don't pivot, I get this answer (with some rounding error on x). When I add in the pivoting, I get the same numbers but in the wrong order: w=2,x=1,y=-1 and z=0.
What do I need to do to get these in the correct order? Am I missing a step somewhere? I need to do column swapping instead of rows because I need to adapt this to a parallel algorithm later that requires that. Here is the code that does the elimination and back substitution:
void gaussian_elimination(double** A, double* b, double* x, int n)
{
int maxIndex;
double temp;
int i;
for (int k = 0; k < n; k++)
{
i = k;
for (int j = k+1; j < n; j++)
{
if (abs(A[k][j]) > abs(A[k][i]))
{
i = j;
}
}
if (i != k)
{
for (int j = 0; j < n; j++)
{
temp = A[j][k];
A[j][k] = A[j][i];
A[j][i] = temp;
}
}
for (int j = k + 1; j < n; j++)
{
A[k][j] = A[k][j] / A[k][k];
}
b[k] = b[k] / A[k][k];
A[k][k] = 1;
for (i = k + 1; i < n; i++)
{
for (int j = k + 1; j < n; j++)
{
A[i][j] = A[i][j] - A[i][k] * A[k][j];
}
b[i] = b[i] - A[i][k] * b[k];
A[i][k] = 0;
}
}
}
void back_substitution(double**U, double*x, double*y, int n)
{
for (int k = n - 1; k >= 0; k--)
{
x[k] = y[k];
for (int i = k - 1; i >= 0; i--)
{
y[i] = y[i] - x[k]*U[i][k];
}
}
}
I believe what you implemented is actually complete pivoting.
With complete pivoting, you must keep track of the permutation of columns, and apply the same permutation to your answer.
You can do this with an array {0, 1, ..., n}, where you swap the i'th and k'th values in the second loop. Then, rearange the solution using this array.
If what you were trying to do is partial pivoting, you need to look for the maximum in the respective row, and swap the rows and the values of 'b' accordingly.
I recently turned in homework which I had thought I had done correct but my teacher marked me for things that I honestly thought were right.
The first question: Fill up the following code for computing the sum of values on the principal and minor diagonal in a square matrix A[7][7]. Assume the matrix is defined
int sum = 0; // he marked this wrong. Why is initializing to 0 wrong?
for(int i = 0; i < 7; i++) {
for(int j = 0; j < 7; j++) { // also marked j < 7 wrong
sum = sum + A[i][i] + A[i][7-1-i]
}
return sum;
}
Question 2: Transpose a square matrix A[50][50] i.e., the first row becomes the first column and vice-versa, the second row becomes the second column and so on. Assume the matrix is defined.
void transposeSquare(){
for(int i=0;i<50;i++){
for(int j=0;j<50;j++){ //marked j=0 wrong
int temp = A[i][i];
A[i][j] = A[j][i];
A[j][i] = temp;
}
}
}
Why is j=0 in transposeSquare not right?
Why would sum be anything other than 0?
If i < 7 should j < 7 too if its a square matrix?
Thanks!
Your logic is wrong for couple of reasons.
By using a nested loop inside the outer loop, you are adding the numbers in the diagonals 7 times instead of just once.
When i is 3, the line
sum = sum + A[i][i] + A[i][7-1-i]
is equivalent to:
sum = sum + A[3][3] + A[3][7-1-3]
which is the same as:
sum = sum + A[3][3] + A[3][3]
Adding A[3][3] twice to the sum is not correct.
To fix the problems, use:
for(int i = 0; i < 7; i++){
sum = sum + A[i][i] + A[i][7-1-i];
}
sum -= A[3][3]; // Remove the element that was added twice.
You can use += to simplify the code a little bit.
for(int i = 0; i < 7; i++){
sum += A[i][i] + A[i][7-1-i];
}
sum -= A[3][3]; // Remove the element that was added twice.
Your code has small errors that's why your teacher has entitled your code as wrong.
For the first part,
int sum = 0;
int size = 7;
for(int i = 0; i < size; i++) {
sum += A[i][j] + A[i][sz-1-i]; // Error: Typo, it should be A[i][j] instead of A[i][i]
}
if(size%2 != 0)
sum -= A[size/2][size/2]; // Missed Case: Subtract the middle element since its repeated only when the size of array is an odd number
return sum; // Return the sum at the end!
For second Part You don't need to iterate the whole two-D array. Because if you do so it will copy upper triangle into lower triangle instead of calculating the Transpose. So traverse any triangle (Upper or Lower).
Like I have traversed Lower Triangle in this code.
void transposeSquare(){
for(int i=0;i<50;i++){
for(int j=0; j<i ;j++){ // Fix 1: Loop j to i-1
int temp = A[i][j]; // Fix 2: Typo it should be A[i][j] instead of A[i][i]
A[i][j] = A[j][i];
A[j][i] = temp;
}
}
}
Checkout Triangular Matrix for better explanation.
So far I have this code for an LU decomposition. It takes in an input array and it returns the lower and upper triangular matrix.
void LUFactorization ( int d, const double*S, double*L, double*U )
{
for(int k = 0; k < d; ++k){
if (
for(int j = k; j < d; ++j){
double sum = 0.;
for(int p = 0; p < k; ++p) {
sum+=L[k*d+p]*L[p*d+j];
cout << L[k*d+p] << endl;
}
sum = S[k*d+j] - sum;
L[k*d+j]=sum;
U[k*d+j]=sum;
}
for(int i = k + 1; i < d; ++i){
double sum=0.;
for(int p = 0; p < k; ++p) sum+=L[i*d+p]*L[p*d+k];
L[i*d+k]=(S[i*d+k]-sum)/L[k*d+k];
}
}
for(int k = 0; k < d; ++k){
for(int j = k; j < d; ++j){
if (k < j) L[k*d+j]=0;
else if (k == j) L[k*d+j]=1;
}
}
}
Is there some way I can adapt this to perform row exchanges? If not, is there some other algorithm I could be directed towards?
Thanks
The usual approach for LU decompositions with pivoting is to store a permutation array P which is initialized as the identity permutation (P={0,1,2,...,d - 1}) and then swapping entries in P instead of swapping rows in S
If you have this permutation array, every access to S must use P[i] instead of i for the row number.
Note that P itself is part of the output, since it represents the permutation matrix such that
P*A = L*U, so if you want to use it to solve systems of linear equations, you'll have to apply P on the right-hand side before applying backward and forward substitution
i want to potentiate a Matrix but i dont workings how it should work.
m ist the Matrix i want to potentiate
long double pro[100][100]; // product after each step
long double res[100][100]; // the Matrix with the exponent n
for (int n = 1; n < nVal; n++) // exponent
{
for (int i = 0; i < mVal; i++) // row
{
for (int j = 0; j < mVal; j++) // col
{
res[i][j] = 0;
for (int k = 0; k < mVal; k++) // inner
{
res[i][j] += pro[i][k] * m[k][j]; // multiply the product with the default matrix
}
}
}
}
// array Output - working
for (int i = 0; i<mVal; i++)
{
for (int j = 0; j<mVal; j++)
cout << res[i][j] << "\t";
cout << endl;
}
in the output i see some crazy numbers and i dont know why :(
Can anyone help me?
You should
initialise the pro matrix to the identity at the beginning of loop on n
copy the res matrix into the pro matrix the end of each loop on n.
In pseudo code
pro = Identity matrix
for (int n = 1; n < nVal; n++) {
res = pro * m // using two loops
pro = res
}
result is in pro.
Note that there are much faster way to compute powers: http://en.wikipedia.org/wiki/Exponentiation_by_squaring
As Willll said you shouldn't forget to initialize.
Another suggestion would be to erase the exponent loop and just use the pow() function from math library. It´ll make it more simple and easier to visualize.
Two Egg problem:
You are given 2 eggs.
You have access to a 100-storey building.
Eggs can be very hard or very fragile means it may break if dropped from the first floor or may not even break if dropped from 100 th floor.Both eggs are identical.
You need to figure out the highest floor of a 100-storey building an egg can be dropped without breaking.
Now the question is how many drops you need to make. You are allowed to break 2 eggs in the process.
I know the solution for this problem with dynamic programming. I want to trace the solution along with the minimum number of tries. i.e the floors that I have to try for getting the minimum number of tries.
# include <stdio.h>
# include <limits.h>
// A utility function to get maximum of two integers
int max(int a, int b) { return (a > b)? a: b; }
/* Function to get minimum number of trails needed in worst
case with n eggs and k floors */
int eggDrop(int n, int k)
{
/* A 2D table where entery eggFloor[i][j] will represent minimum
number of trials needed for i eggs and j floors. */
int eggFloor[n+1][k+1];
int res;
int i, j, x;
// We need one trial for one floor and0 trials for 0 floors
for (i = 1; i <= n; i++)
{
eggFloor[i][1] = 1;
eggFloor[i][0] = 0;
}
// We always need j trials for one egg and j floors.
for (j = 1; j <= k; j++)
eggFloor[1][j] = j;
// Fill rest of the entries in table using optimal substructure
// property
for (i = 2; i <= n; i++)
{
for (j = 2; j <= k; j++)
{
eggFloor[i][j] = INT_MAX;
for (x = 1; x <= j; x++)
{
res = 1 + max(eggFloor[i-1][x-1], eggFloor[i][j-x]);
if (res < eggFloor[i][j])
eggFloor[i][j] = res;
}
}
}
// eggFloor[n][k] holds the result
return eggFloor[n][k];
}
/* Driver program to test to pront printDups*/
int main()
{
int n = 2, k = 36;
printf ("\nMinimum number of trials in worst case with %d eggs and "
"%d floors is %d \n", n, k, eggDrop(n, k));
return 0;
}
You just need to store the value of x that gives you the optimal solution:
int eggDrop(int n, int k)
{
/* A 2D table where entery eggFloor[i][j] will represent minimum
number of trials needed for i eggs and j floors. */
int eggFloor[n+1][k+1];
int floor[n+1][k+1];
int res;
int i, j, x;
// We need one trial for one floor and0 trials for 0 floors
for (i = 1; i <= n; i++)
{
eggFloor[i][1] = 1;
eggFloor[i][0] = 0;
}
// We always need j trials for one egg and j floors.
for (j = 1; j <= k; j++)
eggFloor[1][j] = j;
// Fill rest of the entries in table using optimal substructure
// property
for (i = 2; i <= n; i++)
{
for (j = 2; j <= k; j++)
{
eggFloor[i][j] = INT_MAX;
for (x = 1; x <= j; x++)
{
res = 1 + max(eggFloor[i-1][x-1], eggFloor[i][j-x]);
if (res < eggFloor[i][j]) {
eggFloor[i][j] = res;
floor[i][j] = x;
}
}
}
}
// eggFloor[n][k] holds the result
return eggFloor[n][k];
}
In the end, floor[i][j] contains the floor you need to try when you have i eggs and j floors.