The nested if statement I've tried writing keeps returning an error but I can't see where. I've seen similar threads but none with a workable syntax. I've tried with and without the and statement. Very simply looking at the value in a cell (C5) and returning a corresponding value-based what the number in C5 is.
=if(C5>84.5,1,if(and(C5<=84.5,C5>79.5,1.3,if(and(C5<=79.5,C5>74.5,1.7,if(and(C5<=74.5,C5>69.5,2,if(and(C5<=69.5,C5>64.5,2.3,if(and(C5<=64.5,C5>59.5,2.7,if(and(C5<=59.5,C5>54.5,3,if(and(C5<=54.5,C5>49.5,3.3,if(and(C5<=49.5,C5>44.5,3.7,if(and(C5<=44.5,C5>=40,4,if(C5<40,5))))))))))))))))))))
I expect the output to range from 1 to 5 depending on what the value in cell C5 is but I keep getting the following error
Wrong number of arguments to IF. Expected between 2 and 3 arguments,
but got 1 argument
You systematically forgot to close the parentheses of your and() functions. Try this:
=if(C5>84.5,1,if(and(C5<=84.5,C5>79.5),1.3,if(and(C5<=79.5,C5>74.5),1.7,if(and(C5<=74.5,C5>69.5),2,if(and(C5<=69.5,C5>64.5),2.3,if(and(C5<=64.5,C5>59.5),2.7,if(and(C5<=59.5,C5>54.5),3,if(and(C5<=54.5,C5>49.5),3.3,if(and(C5<=49.5,C5>44.5),3.7,if(and(C5<=44.5,C5>=40),4,if(C5<40,5)))))))))))
if you need ArrayFormula use:
=ARRAYFORMULA(
IF( C5:C > 84.5, 1,
IF((C5:C <= 84.5) * (C5:C > 79.5), 1.3,
IF((C5:C <= 79.5) * (C5:C > 74.5), 1.7,
IF((C5:C <= 74.5) * (C5:C > 69.5), 2,
IF((C5:C <= 69.5) * (C5:C > 64.5), 2.3,
IF((C5:C <= 64.5) * (C5:C > 59.5), 2.7,
IF((C5:C <= 59.5) * (C5:C > 54.5), 3,
IF((C5:C <= 54.5) * (C5:C > 49.5), 3.3,
IF((C5:C <= 49.5) * (C5:C > 44.5), 3.7,
IF((C5:C <= 44.5) * (C5:C >= 40), 4,
IF( C5:C < 40, 5))))))))))))
Related
I'm wondering if there is any easier way to prevent accessing array beyond range than using if() statement.
I have switch case code for arduino like this with many cases:
switch(a){
case 3:
case 27:
for (int i = 0; i < 8; i++){
leds[ledMapArray[x][i]] = CRGB(0,255,0);
leds[ledMapArray[i][y]] = CRGB(0,255,0);
if ((x + i < 8) && (y + i < 8)) leds[ledMapArray[x + i][y + i]] = CRGB(0,255,0);
if ((x - i >= 0) && (y - i >= 0)) leds[ledMapArray[x - i][y - i]] = CRGB(0,255,0);
if ((x + i < 8) && (y - i >= 0)) leds[ledMapArray[x + i][y - i]] = CRGB(0,255,0);
if ((x - i >= 0) && (y + i < 8)) leds[ledMapArray[x - i][y + i]] = CRGB(0,255,0);
}
break;
case 4:
case 28:
if (x + 1 < 8) leds[ledMapArray[x + 1][y]] = CRGB(0,255,0);
if (x - 1 >= 0) leds[ledMapArray[x - 1][y]] = CRGB(0,255,0);
if (y - 1 >= 0) leds[ledMapArray[x][y - 1]] = CRGB(0,255,0);
if (y + 1 < 8) leds[ledMapArray[x][y + 1]] = CRGB(0,255,0);
if ((x + 1 < 8) && (y + 1 < 8)) leds[ledMapArray[x + 1][y + 1]] = CRGB(0,255,0);
if ((x - 1 >= 0) && (y - 1 >= 0)) leds[ledMapArray[x - 1][y - 1]] = CRGB(0,255,0);
if ((x + 1 < 8) && (y - 1 >= 0)) leds[ledMapArray[x + 1][y - 1]] = CRGB(0,255,0);
if ((x - 1 >= 0) && (y + 1 < 8)) leds[ledMapArray[x - 1][y + 1]] = CRGB(0,255,0);
break;
...
ledMapArray is 8x8 array where x and y value may be <7,0>. Here are some definitions:
// CRGB is structure from FastLed library
CRGB leds[NUM_LEDS]; // from FastLed library to control LED strip
// Array to show how LED strip looks like, values in array represents leds
const short ledMapArray[8][8] = {{0, 1, 2, 3, 4, 5, 6, 7},
{15, 14, 13, 12, 11, 10, 9, 8},
{16, 17, 18, 19, 20, 21, 22, 23},
{31, 30, 29, 28, 27, 26, 25, 24},
{32, 33, 34, 35, 36, 37, 38, 39},
{47, 46, 45, 44, 43, 42, 41, 40},
{48, 49, 50, 51, 52, 53, 54, 55},
{63, 62, 61, 60, 59, 58, 57, 56}};
The point of this switch case is to light up specific LEDs from LED strip. I want to show allowed moves for chess pieces on smart chessboard.
Is there any better way to do this?
The Answer was written when the question used the tag c, not c++ and edited later. The FastLED library is clearly implemented in C++.
You could wrap the array access in a function that implements the checks.
The following function assumes that the array leds and ledMapArray are file scope variables. Otherwise the function would need more arguments. In C++, the function will also work if the function and the variables are members of the same class.
Instead of a hard-coded number 8, the check should better be implemented based on the number of elements in the array. (Something like sizeof(array)/sizeof(array[0]). I would need to see the definition of leds and ledMapArray.)
Note that the function implements a bounds check for ledMapArray only, not for leds.
void setLed(int x, int y, some_type crgb)
{
if((x >= 0) && (x < 8) && (y >= 0) && (y < 8))
{
leds[ledMapArray[x][y]] = crgb;
}
}
The function could also be replaced with a macro which would work for local array variables as well as for global variables.
#define setLed(x, y, crgb) do { \
if((x >= 0) && (x < 8) && (y >= 0) && (y < 8)) { \
leds[ledMapArray[x][y]] = crgb; \
} \
} while(0)
switch(x){
case 3:
case 27:
for (int i = 0; i < 8; i++){
setLed(x, i, CRGB(0,255,0));
setLed(i, y, CRGB(0,255,0));
setLed(x + i, y + i, CRGB(0,255,0));
setLed(x - i, y - i, CRGB(0,255,0));
setLed(x + i, y - i, CRGB(0,255,0));
setLed(x - i, y + i, CRGB(0,255,0));
}
break;
case 4:
case 28:
setLed(x + 1, y, CRGB(0,255,0));
/* etc ... */
Instead of repeatedly using anonymous objects with the same constructor CRGB(0,255,0), you could use a named object.
CRGB greenColor(0,255,0);
setLed(x, i, greenColor);
setLed(i, y, greenColor);
/* etc ... */
Or use pre-defined color objects from the library.
setLed(x, i, CRGB::Green);
setLed(i, y, CRGB::Green);
/* etc ... */
A given list is n=[3,1,5,9,6,14] , replace 5 with 3+1 and 14 with 9+6. The output will look like [3,1,4,9,6,15]
My approach was using a range and assign value
i+ [i+1]==[i+2]
I tried 2 ways but in both cases I am getting out of bound exception
#Approach 1
for idx,item in enumerate(n):
if (idx + (idx+1))!=(idx+2):
n[idx+2]=(idx + (idx+1))
#Approach2
for i in range(len(n)):
if n[i]+n[i+1]!=n[i+2]:
n[i + 2]==n[i]+n[i+1]
print(n)
Even doing a len(n)-1 does not solve the problem. Some directions will be helpful. Thank You.
You could use the mod (%) operator to check for every third item:
items = [3, 1, 5, 9, 6, 14]
for i, item in enumerate(items):
if ((i+1) % 3 == 0):
items[i] = items[i-1] + items[i-2]
print(items)
Or to be more efficient, use range as mentioned in the comments:
for i in range(2, len(items), 3):
items[i] = items[i-1] + items[i-2]
print(items)
I am reading about shell sort in Algorithms in C++ by Robert Sedwick.
Here outer loop to change the increments leads to this compact shellsort implementation, which uses the increment sequence 1 4 13 40 121 364 1093 3280 9841 . . . .
template <class Item>
void shellsort(Item a[], int l, int r)
{
int h;
for (h = 1; h <= (r - l) / 9; h = 3 * h + 1);
for (; h > 0; h = h / 3)
{
for (int i = l + h; i <= r; i++)
{
int j = i; Item v = a[i];
while (j >= l + h && v < a[j - h])
{
a[j] = a[j - h]; j -= h;
}
a[j] = v;
}
}
}
My question under what basis author is checking for condition h <= (r-l)/9, and why author is dividing by 9.
The loop:
for (h = 1; h <= (r - l) / 9; h = 3 * h + 1);
calculates the initial value of h. This value must be smaller than the range it will be used in:
h <= (r - l)
Everytime this condition passes, h gets updated to 3 * h + 1, which means that even though h is smaller than (r-l), the updated value might be larger. To prevent this, we could check if the next value of h would surpass the largest index:
(h * 3) + 1 <= (r - l)
This will make sure h is smaller than range of the array.
For example: say we have an array of size 42, which means indices go from 0 to 41. Using the condition as described above:
h = 1, is (3 * 1 + 1) <= (41 - 0) ? yes! -> update h to 4
h = 4, is (3 * 4 + 1) <= (41 - 0) ? yes! -> update h to 13
h = 13, is (3 * 13 + 1) <= (41 - 0) ? yes! -> update h to 40
h = 40, is (3 * 40 + 1) <= (41 - 0) ? no! => h will begin at 40
This means our initial h is 40, because h is only marginally smaller than the range of the array, very little work will be done, the algorithm will only check the following:
Does array[40] needs to be swapped with array[0] ?
Does array[41] needs to be swapped with array[1] ?
This is a bit useless, the first iteration only performs two checks. A smaller initial value of h means more work will get done in the first iteration.
Using:
h <= (r - l) / 9
ensures the initial value of h to be sufficiently small to allow the first iteration to do useful work. As an extra advantage, it also looks cleaner than the previous condition.
You could replace 9 by any value greater than 3. Why greater than 3? To ensure (h * 3) + 1 <= (r - l) is still true!
But do remember to not make the initial h too small: Shell Sort is based on Insertion Sort, which only performs well on small or nearly sorted arrays. Personally, I would not exceed h <= (r - l) / 15.
I'm trying to calculate the points in a cuboid given its centre (which is a Vector3) and the lengths of the sides along the x, y and z axis. I found the following on math.stackexchange.com: https://math.stackexchange.com/questions/107778/simplest-equation-for-drawing-a-cube-based-on-its-center-and-or-other-vertices which says I can use the following formulae:
The constructor for the World class is:
World::World(Vector3 o, float d1, float d2, float d3) : origin(o)
{
// If we consider an edge length to be d, we need to find r such that
// 2r = d in order to calculate the positions of each vertex in the world.
float r1 = d1 / 2,
r2 = d2 / 2,
r3 = d3 / 2;
for (int i = 0; i < 8; i++)
{
/* Sets up the vertices of the cube.
*
* #see http://bit.ly/1cc2RPG
*/
float x = o.getX() + (std::pow(-1, i&1) * r1),
y = o.getY() + (std::pow(-1, i&2) * r2),
z = o.getZ() + (std::pow(-1, i&4) * r3);
points[i] = Vector3(x, y, z);
std::cout << points[i] << "\n";
}
}
And I passing the following parameters to the constructor:
Vector3 o(0, 0, 0);
World w(o, 100.f, 100.f, 100.f);
The coordinates being output for all 8 vertices are:
(50, 50, 50)
(-50, 50, 50)
(50, 50, 50)
(-50, 50, 50)
(50, 50, 50)
(-50, 50, 50)
(50, 50, 50)
(-50, 50, 50)
Which cannot be correct. Any guidance would be very much appreciated!
The problem lies in the bitwise & inside your pow calls:
In the y and z components, they always return 0 and 2 or 4, respectively. -1^2 = -1^4 = 1, which is why the sign of these components is always positive. You could try (i&2)!=0 or (i&2) >> 1 for the y component instead. The same goes for the z component.
Change this:
float x = o.getX() + (std::pow(-1, i&1) * r1),
y = o.getY() + (std::pow(-1, i&2) * r2),
z = o.getZ() + (std::pow(-1, i&4) * r3);
To this:
float x = o.getX() + (std::pow(-1, (i ) & 1) * r1), // pow(-1, 0) == 1, pow(-1, 1) == -1
y = o.getY() + (std::pow(-1, (i >> 1) & 1) * r2), // pow(-1, 0) == 1, pow(-1, 1) == -1
z = o.getZ() + (std::pow(-1, (i >> 2) & 1) * r3); // pow(-1, 0) == 1, pow(-1, 1) == -1
Or even to this:
float x = o.getX() + (std::pow(-1, (i )) * r1), // pow(-1, {0, 2, 4, 6}) == 1, pow(-1, {1, 3, 5, 7}) == -1
y = o.getY() + (std::pow(-1, (i >> 1)) * r2), // pow(-1, {0, 2}) == 1, pow(-1, {1, 3}) == -1
z = o.getZ() + (std::pow(-1, (i >> 2)) * r3); // pow(-1, 0) == 1, pow(-1, 1) == -1
The problem is that as written even though the values you mask out identify weather or not the lengths need to be negated. They are not in the correct place value to get the desired properties from the exponentiation of -1.
Rewriting the code as I have above will solve this issue, however it would be more readable and in general more permanent just to unroll the loop and manually write if each one is an addition or subtraction without using the pow function.
My understanding is that (one use of) numpy's vectorize allows me to send an array to a function that normally only takes scalars, instead of using the built in map function (in combination with a lambda function or the like). However, under the following scenario I am getting different results when I use map vs numpy.vectorize and I can't seem to figure out why.
import numpy as np
def basis2(dim, k, x):
y = np.array([-0.2, -0.13, -0.06, 0, 0.02, 0.06, 0.15, 0.3, 0.8,
1.6, 3.1, 6.1, 10.1, 15.1, 23.1, 30.1, 35.0, 40.0, 45.0, 50.0, 55.0])
if x < y[k] or x > y[k + dim + 1]:
return 0
elif dim != 0:
ret = ((x - y[k]) / (y[k + dim] - y[k])) * basis2(dim - 1, k, x) + (
(y[k + dim + 1] - x) / (y[k + dim + 1] - y[k + 1])) * basis2(dim - 1, k + 1, x)
return ret
else:
return 1.0
w = np.array([20.0, 23.1, 30.0])
func = lambda x: basis2(3, 14, x)
vec = map(func, w)
func2 = np.vectorize(basis2)
vec2 = func2(3, 14, w)
print vec # = [0, 0.0, 0.23335417007039491]
print vec2 # = [0 0 0]
As the docstring says:
The data type of the output of vectorized is determined by calling
the function with the first element of the input. This can be avoided
by specifying the otypes argument.
you need to add a otypes argument:
func2 = np.vectorize(basis2, otypes="d")
or change return 0 to return 0.0 in basis2().