Given a binary matrix, we want to check if there exists a path across nodes on two ends, such as:
0 1 0 0 0
0 1 1 0 0
0 0 1 1 0
0 0 0 1 0
this case has a chain of one's from the first to the last row which is stretched over in some of the rows. Similarly, the result should be true even if there's a chain from left to the right column.
I thought about writing a recursively exploring function for each positive element through-out the top row and the left column. Could you suggest something better?
one of solutions would be to use Set:
Go through each row
If field value is 1 and one of its already visited neighbours is inside the Set, add its coordinates (x,y) to the Set
At the end, check if Set contains any coordinates from the last row - if so, there is a path.
as you didn't mention which language you would like to use, here's how it looks like in Javascript (ES6):
let matrix = '01000
01100
00110
00010'.split('\n').map((row) => { return row.split('') });
let set = new Set();
let cols = matrix[0].length;
let rows = matrix.length;
for(let col=0; col < cols; col++){
if(matrix[0][col] == '1'){
set.add(`0,{col}`);
}
}
for(let row=1; row < rows-1; row++){
for(let col=1; col < cols; col++){
if(matrix[row][col] == '1' &&
(set.has(`{row-1},{col-1}`) ||
set.has(`{row-1},{col}`) ||
set.has(`{row-1},{col+1}`) ||
set.has(`{row},{col-1}`))){
set.add(`{row},{col}`);
}
}
}
let row = rows-1;
for(let col=0; col < cols; col++){
if(matrix[row][col] == '1' &&
(set.has(`{row-1},{col-1}`) ||
set.has(`{row-1},{col}`) ||
set.has(`{row-1},{col+1}`) ||
set.has(`{row},{col-1}`))){
// HAS PATH
}
}
Related
So I want to use Google spreadsheet to find how many times does five consecutive cells have a value greater than a given value in a row,but one cell cant be a part of two set of consecutive cells.For example i want to count the number of times a particular item was bought in a month for consecutive five days but if it was bought for 7 days at a stretch it will only be counted as one whereas if it is multiple of five it will be counted as many multiples of five.
For Ex:If cells 1-5 have a value greater than the given value it should give me a count of 1, but if cells 1-9 also are greater than the given value even then it should give me count of 1 but if 1-10 have a value greater than the given value then it should give me a count of 2.I hope this was clear.
I want to write this code in Google Drive using custom function, I tried writing a code in C.
*
int x; //no. of rows
int y; //no. of columns
int arr[x][y]; //array to store numbers
int count[x];
int i,j,k; //for loops
for(i=0;i<x;i++) //set count to 0 for all rows
count[x]=0;
for(i=0;i<x;i++)
{
for(j=0;j<y;j++)
{
for(k=1;k<=5, j<y;k++, j++)
{
if(!arr[i][j]>0)
{
break;
}
else if(k==5 && arr[i][j]!<1)
{
count[i]++;
j--;
}
}
}
}
//display the count array now to see result.
*
You can do this without writing code. That's kinda the purpose of a spreadsheet.
You have one column, say column A, with the values.
In the next column, start a counter that increments each row if the value in the first column is >= your preset value, and reset the counter if not. The formula would be something like (for cell B2)
=IF(A2>=$E$1,B1+1,0)
In the next column, calculate the multiples of 5. For cell C2:
=IF(MOD(B2,5)=0,C1+1,C1)
Copy those cells down to the bottom of the list in column A, and the last value will be the count of values that exceeded cell $e1 a multiple of 5 consecutive times.
Another way using native Sheets functions:
=ArrayFormula((ROWS(A:A)-LEN(REGEXREPLACE(CONCATENATE(LEFT(A:A>=1)),"TTTTT","")))/5)
and using a custom function:
function countGroups(range, comparisonValue, groupSize) {
var v = comparisonValue || 1; // default to comparing to 1 if not specified
var n = groupSize || 5; // default to groups of 5 if not specified
var count = 0, counter = 0;
for (var i = 0, length = range.length; i < length; i++) {
if (range[i][0] >= v) {
counter++;
if (counter == n) {
counter = 0;
count++;
}
}
else
counter = 0;
}
return count;
}
I've recently come across the following problem:
Let say I have an vector of random length (L) of 0 and 1 randomly distributed (for example [0,1,1,1,0,0,1,0]), I need to split the vector in two sub-vector at index K so following conditions are valid:
the left sub-vector must contains the maximum number of elements from
K in reverse order such as the number of zeros must be greater or
equal to the number of 1s
the right sub vector must contains the maximum number of element starting from K+1 such as the number of 1s must be greater or equal to the number of zeros
For example, [1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0,0] the split is at index 9, left vector is [1,0], right vector [0,1]
I wrote the following solution but the complexity is O(L^2). I think there could be a solution with complexity of worst case O(L) but I cannot find anything that can help me. Any idea? Thanks
var max = 0;
var kMax = -1;
var firstZeroFound = false;
for (var i = 0; i < testVector.Length - 1; i++)
{
if (!firstZeroFound)
{
if (testVector[i]) continue;
firstZeroFound = true;
}
var maxZero = FindMax(testVector, i, -1, -1, false);
if (maxZero == 0) continue;
var maxOne = FindMax(testVector, i + 1, testVector.Length, 1, true);
if (maxOne == 0) continue;
if ((maxZero + maxOne) <= max)
continue;
max = maxOne + maxZero;
kMax = i;
if (max == testVector.Length)
break;
}
Console.Write("The result is {0}", kMax);
int FindMax(bool[] v, int start, int end, int increment, bool maximize)
{
var max = 0;
var sum = 0;
var count = 0;
var i = start;
while (i != end)
{
count++;
if (v[i])
sum++;
if (maximize)
{
if (sum * 2 >= count)
max = count;
}
else if (sum * 2 <= count)
{
max = count;
}
i += increment;
}
return max;
}
I think you should look at rle.
y <- c(1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0,0)
z <- rle(y)
d <- cbind(z$values, z$lengths)
[,1] [,2]
[1,] 1 9
[2,] 0 1
[3,] 1 1
[4,] 0 8
Basically, rle calculates the lengths of 0's and 1's at each level.
From here things may go easier for you.
I have 2 variables, width and height as integers. Any of these can be positive or negative (not zero). So naturally there are 4 cases;
width > 0 && height > 0
width > 0 && height < 0
width < 0 && height > 0
width < 0 && height < 0
Now I want to take different action on each of these 4 cases without using 4 if statements.
Is there a way to aggregate these cases so that it can be put as a simple switch case
switch( aggregate ){
case 1:
case 2:
case 3:
case 4:
}
If there is no better way than using if for each then in 3D space you have 3 lengths (x,y,z) and there will be 27 if blocks.
I'm using javascript if that matters.
In javascript this is quite easy, just turn the condition upside down:
switch(true)
{
case (width > 0 && height > 0):
break;
case (width > 0 && height < 0):
break;
case (width < 0 && height > 0):
break;
case (width < 0 && height < 0):
break;
default:
}
This also works in VB6/VBA but not in many other languaguages like C++ and C#.
Here's a simple proof: http://jsfiddle.net/avuxj/
You could treat each of your conditions (width positive, height positive) as a single boolean attribute and combine them to binary number and switch over it.
Pseudocode:
int v = (width > 0 ? 0 : 1) << 1 | (height > 0 ? 0 : 1) << 0;
switch (v) {
case 0b00:
// width < 0 && height < 0;
break;
case 0b01:
// width < 0 && height > 0;
break;
case 0b10:
// width > 0 && height < 0
break;
case 0b11:
// width > 0 && height > 0
break;
}
If the language of your choice doesn't have binary numeric literals, then it's not as readable, but you might be able to fix that with comments.
Also note that languages that support interpreting true as 1 and false as 0 will help make the int v = ... line shorter.
You could do
var bits=0;
if(width > 0) {
bits+=1;
}
if(height > 0) {
bits+=2;
}
switch{bits} {
case 0: //both negative
//something
break;
case 1: //width positive, height negative
//something
break;
case 2: //width negative, height positive
//something
break;
case 3: //both positive
//something
break;
}
Although it is all bit confusing. (Especially if You have 3 values). You can use variables to make Your code bit clearer.
var WIDTH_POSITIVE_BIT=1;
var HEIGHT_POSITIVE_BIT=2;
var bits=0;
if(width > 0) {
bits+=WIDTH_POSITIVE_BIT;
}
if(height > 0) {
bits+=HEIGHT_POSITIVE_BIT;
}
switch{bits} {
case 0: //both negative
//something
break;
case WIDTH_POSITIVE_BIT: //width positive, height negative
//something
break;
case HEIGHT_POSITIVE_BIT: //width negative, height positive
//something
break;
case WIDTH_POSITIVE_BIT+HEIGHT_POSITIVE_BIT: //both positive
//something
break;
}
I'd say that this does not help to make the code much clearer.
Can't do this without adding a little overhead.
s = ( width < 0 ) ? 0 : 1;
s += ( height < 0 ) ? 0 : 2;
switch(s) {
case 0: // 00 => both < 0
case 1: // 01 => width > 0, height < 0
case 2: // 10 => width < 0, height > 0
case 3: // 11 => both > 0
}
And this could work for a 3D case:
s = ( width < 0 ) ? 0 : 1; //First bit for width
s += ( height < 0 ) ? 0 : 2; //Second bit for height
s += ( depth < 0 ) ? 0 : 4; //Third bit for depth
switch(s) {
case 0: // 0 0 0
case 1: // 0 0 1
case 2: // 0 1 0
case 3: // 0 1 1
case 4: // 1 0 0
case 5: // 1 0 1
case 6: // 1 1 0
case 7: // 1 1 1
}
Of course assuming you can't have a 0 dimension.
Several answers are logically correct. If you were doing this in C it would be:
s = ((width<0)<<1) | (height<0);
switch(s) {
....
}
This can make a huge difference. I have code that combines 9 conditions into a switch like this. The switch gets turned into a jump table and is much faster than evaluating a bunch of conditions. There is no branching, just the jump table. I can't really speak to anything java or java script though.
You may also do nested if statements:
if (witdh<0) {
if (height<0) {
// both negative
}
else {
// only width negative
}
}
else {
if (height<0) {
// only height negative
}
else {
// both positive
}
}
I find mashing the condition bits together and using a switch to be more readable - especially if the number of conditions grows.
How do you fake conditionals that don't nest in a language that doesn't allow goto? I want to do the following:
if (condition1)
action1;
if (!condition1 && condition2)
action2;
if (!condition2 && condition3)
action3;
Without:
Needlessly evaluating any condition more than once.
Needlessly storing the result of any such evaluation in a variable.
Needlessly specifying more than once that any action should be performed.
The original snippet fails to meet requirement 1.
The following snippet fails to meet requirement 2:
if (condition1) {
action1;
c2 = false;
}
else if (c2 = condition2)
action2;
if (!c2 && condition3)
action3;
And the following snippet fails to meet requirement 3:
if (condition1) {
action1;
if (condition3)
action3;
}
else if (condition2)
action2;
else if (condition3)
action3;
EDIT:
It is impossible that condition1 and condition2 be true simultaneously.
It is impossible that condition2 and condition3 be true simultaneously.
Here is the original code (in JavaScript):
// If only the array of elements was specified,
// wrap it inside an object.
if (info.constructor !== Object)
info = {children: info};
// If no array of elements was specified, create
// an empty array of elements.
if (!info.children)
info.children = [];
// If, instead of an array of elements, we have
// a single element, wrap it inside an array.
if (info.children.constructor !== Array)
info.children = [info.children];
Truth Table
C1 C2 C3 Action
0 0 0 None
0 0 1 A3
0 1 0 A2
0 1 1 A2
1 0 0 A1
1 0 1 A1+A3
1 1 0 A1
1 1 1 A1
Is switch/case against the rules? :)
switch(C1*4 + C2*2 + C1) {
case 7: case 6: case 4: A1; break;
case 5: A1; A3; break;
case 3: case 2: A2; break;
case 1: A3; break;
}
So how do you do this with goto anyway? This immediately comes to mind, but doesn't have quite the same result:
if(condition1) {
action1;
goto a;
}
if(condition2) {
action2;
goto b;
}
a:
if(condition3) {
//This will run if condition1 && condition2 && condition3
action3;
}
b:
Either way, you do have a few tricks that can break out of nested "if"s. Try:
do {
if(condition1) {
action1;
} elseif(condition2) {
action2;
break;
}
if(condition3) {
action3;
}
} while(false);
It's essentially a goto, but...
That version will duplicate the goto construct that I imagined, rather than the one in the OP. Note that "return" works about the same, in case that looks cleaner in your code (and it might be able to push the hack a bit further by returning a boolean).
Attempts 1 & 2:
Note: Removed first attempts to cut down on question size. See community wiki for previous attempts.
Attempt 3:
As per fuzzy-waffle's example, I have implemented the following, which doesn't appear to work correctly. Any ideas what I could be doing wrong?
ImageMatrix ImageMatrix::GetRotatedCopy(VDouble angle)
{
// Copy the specifications of the original.
ImageMatrix &source = *this;
ImageMatrix &target = CreateEmptyCopy();
double centerX = ((double)(source.GetColumnCount()-1)) / 2;
double centerY = ((double)(source.GetRowCount()-1)) / 2;
// Remember: row = y, column = x
for (VUInt32 y = 0; y < source.GetRowCount(); y++)
{
for (VUInt32 x = 0; x < source.GetColumnCount(); x++)
{
double dx = ((double)x) - centerX;
double dy = ((double)y) - centerY;
double newX = cos(angle) * dx - sin(angle) * dy + centerX;
double newY = cos(angle) * dy + sin(angle) * dx + centerY;
int ix = (int)round(newX);
int iy = (int)round(newY);
target[x][y][0] = source[ix][iy][0];
}
}
return target;
}
With this prototype matrix...
1 2 1
0 0 0
-1 -2 -1
... prototype.GetRotatedCopy(0) (which is correct) ...
1 2 1
0 0 0
-1 -2 -1
... prototype.GetRotatedCopy(90) (incorrect) ...
-2 0 0
-2 0 2
0 0 2
... prototype.GetRotatedCopy(180) (incorrect - but sort of logical?) ...
0 -1 -2
1 0 -1
2 1 0
... prototype.GetRotatedCopy(270) (incorrect - why is this the same as 0 rotation?) ...
1 2 1
0 0 0
-1 -2 -1
Solution:
As pointed out by Mark Ransom, I should be using radians, not degrees; I have adjusted my code as follows:
ImageMatrix ImageMatrix::GetRotatedCopy(VDouble degrees)
{
// Copy the specifications of the original.
ImageMatrix &source = *this;
ImageMatrix &target = CreateEmptyCopy();
// Convert degree measurement to radians.
double angle = degrees / 57.3;
// ... rest of code as in attempt #3 ...
Thanks for all your help guys!
1 2 1
0 0 0
-1 -2 -1
1 2 1
0 0 0
-1 -2 -1
-1 0 1
-2 0 2
-1 0 1
-1 -2 -1
0 0 0
1 2 1
1 0 -1
2 0 -2
1 0 -1
The algorithm, unless I read it wrong, seems to rotate around the point 0,0 which is not what you want. Maybe you need to add height/2 and width/2 to your row and column values before you plug them in.
for (int y = 0; y < 10; y++) {
for (int x = 0; x < 10; x++) {
VUInt32 newX = (cos(angle) * (x-5)) - (sin(angle) * (y-5));
VUInt32 newY = (sin(angle) * (x-5)) + (cos(angle) * (y-5));
target[newY][newX][0] = source[y][x][0];
}
}
This basically adjusts the rotation center from the upper left corner to the center of the image.
Here is a complete example I hacked up:
I think among other things you may have not been using radians (which we all should use and love). I keep the new coordinates in doubles which seemed to make it less finicky. Note that I am not doing bounds checking which I should but I was lazy.
If you need a faster rotation you can always use shearing like this example.
#include <math.h>
#include <stdio.h>
#define SIZEX 3
#define SIZEY 3
int source[SIZEX][SIZEY] = {
{ 1, 0, 0 },
{ 0, 1, 0 },
{ 0, 0, 1 }
};
int target[SIZEX][SIZEY];
int main () {
double angle = M_PI/2.0;
memset(target,0,sizeof(int)*SIZEX*SIZEY);
double centerX = ((double)(SIZEX-1))/2.0;
double centerY = ((double)(SIZEY-1))/2.0;
for (int y = 0; y < SIZEY; y++) {
for (int x = 0; x < SIZEX; x++) {
double dx = ((double)x)-centerX;
double dy = ((double)y)-centerY;
double newX = cos(angle)*dx-sin(angle)*dy+centerX;
double newY = cos(angle)*dy+sin(angle)*dx+centerY;
int ix = (int) round(newX);
int iy = (int) round(newY);
target[x][y] = source[ix][iy];
}
}
for (int i=0;i<SIZEY;i++) {
for (int j=0;j<SIZEX;j++) {
printf("%d ", target[j][i]);
}
printf("\n");
}
}
short answer: you're doing it wrong.
This is essentially a problem in interpolation, and the way you've approached it introduces discontinuities. Fundamentally this is because rotating a lattice (the regular grid your image is laid out on) does not result in another sampling on the same lattice except for very special cases.
There is no single correct way to do this, by the way, but there are various trade offs with respect to speed and accuracy and also what can be assumed about the original signal (image).
So what are your design parameters? Do you need this to be very fast or very accurate? How do you want to handle aliasing?
your formulas for newRow and newColumn are switched. Remember that row = y and column = x.
Rotation
The problem is that your memory accesses are out of bounds.
After rotation your NewRow and NewColumn may be larger than the original width/height of the image. They may even be negative. If you don't take care about that fact, you'll end up with garbage data (best case) or crashes.
The most common way to deal with this is to just ignore all such pixels. You could also clamp or wrap around the valid intervals. This get's a padding or tiling effect.
Here it's shown with ignoring outside pixels.
int width = 10;
int height = 10;
for (int row = 0; row < height; row++)
{
for (int column = 0; column < width; column++)
{
int newRow = (cos(angle) * row) - (sin(angle) * column);
int newColumn = (sin(angle) * row) + (cos(angle) * column);
if ((newRow >=0) && (newRow < width) &&
(newColumn >=0) && (newColumn < height))
{
target[row][column][0] = source[newRow][newColumn][0];
}
}
}