A elegant solution to this repetitive code? - gml

I have this code, but it just looks like there should be a way to do it in fewer lines/code.
if (TargetX > Origin[0] + Range) TargetX = Origin[0] + Range;
if (TargetY > Origin[1] + Range) TargetY = Origin[1] + Range;
if (TargetX < Origin[0] - Range) TargetX = Origin[0] - Range;
if (TargetY < Origin[1] - Range) TargetY = Origin[1] - Range;
I'm using a language called GML, but this should be universal as long as the solution doesn't have any really specific built-in functions.

It's not easy to answer your question. For sure, you can dry your code up.
Observe that you can simplify your call as:
abs(target - origin) < range
This tells you if, in both directions, your target is in the range origin ± range. Now that you know this, you need to take action if your target is outside range. This can be simplified again: you just need to check if target is greater than origin or viceversa.
Finally, you should either use arrays for both target and origin, or define a function that you may call. Apparently, range is identical every time.
You might use a function:
f(target, origin, range) {
if (abs(target - origin) > range) {
target = (target - origin) < 0 ? target-range : target+range
}
}
Now it looks like that your code has become longer, but is also more easy to maintain: reduce the risk of writing > instead of <, change the function once to change all checks and so on.

Related

range() as method argument for loop iterator

this code generates a nice loop :
for i in range(self.ix):
__pyx_t_3 = __pyx_v_self->ix;
__pyx_t_4 = __pyx_t_3;
for (__pyx_t_5 = 0; __pyx_t_5 < __pyx_t_4; __pyx_t_5+=1) {
__pyx_v_i = __pyx_t_5;
but i want to be able to pass this iterator as argument (so i can have different iterators/generators)
if i try this :
cdef ixrange(self): return range(self.ix)
already is too unwieldy and the loop is no longer a simple loop. :
static PyObject *__pyx_f_3lib_10sparse_ary_9SparseAry_ixrange(struct __pyx_obj_3lib_10sparse_ary_SparseAry *__pyx_v_self) {
PyObject *__pyx_r = NULL;
__Pyx_RefNannyDeclarations
__Pyx_RefNannySetupContext("ixrange", 0);
__Pyx_XDECREF(__pyx_r);
__pyx_t_1 = __Pyx_PyInt_From_unsigned_int(__pyx_v_self->ix); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 139, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_1);
__pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_builtin_range, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 139, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_2);
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
__pyx_r = __pyx_t_2;
__pyx_t_2 = 0;
goto __pyx_L0;
/* function exit code */
__pyx_L1_error:;
__Pyx_XDECREF(__pyx_t_1);
__Pyx_XDECREF(__pyx_t_2);
__Pyx_AddTraceback("lib.sparse_ary.SparseAry.ixrange", __pyx_clineno, __pyx_lineno, __pyx_filename);
__pyx_r = 0;
__pyx_L0:;
__Pyx_XGIVEREF(__pyx_r);
__Pyx_RefNannyFinishContext();
return __pyx_r;
}
any way i can make it simple loop again ?
I don't think it is possible.
The effect of for i in range(self.ix): is to generate a range object, and then call next on that range object until a StopIteration exception is raised. That's also the behaviour that Cython takes for general for loops.
There's actually a fairly long list of conditions that have to be met for Cython to transform that into an optimized loop:
range must be used directly - i.e. it = range(...); for i in it won't work because you might need the range object after the loop.
the types of the start and stop point must be integers.
the type of the loop variable must be an integer (Cython can infer this, but if you assign something of a different type to the loop variable then it won't work)
Cython must know that you haven't reassigned range
The sign of the stop variable must be known.
In your case I think you're hoping for Cython to look inside the cdef function and pick out the range. This is beyond what the current optimizer can do. But also, you can override cdef functions in a derived class (in C++ terms, they're "virtual"), so Cython could almost never safely make the optimization.
Cython is usually able to optimize best when you really restrict the types it's working with. The request that it should generate a fast C for loop but also be able to handle arbitrary iterators does not seem realistically achievable.

How to move to another part of the code using an if statement

in my code I have the following if statement:
if (a.count >= 2) {
t2 = array[b % a.count];
array[0] = t2;
}
I have another if statement that goes like the first. What I want it to do is if a <= 0 then goto a certain line, or skip over certain parts of code. How would I do this? I was thinking something along the lines of
if (a.count <= 0) {
goto line 96
}
This wouldn't work, the syntax is wrong, but how would I do this?
Goto statements are generally considered bad programming and excessive utilization of them can lead to code that is hard to maintain and debug.
That said, if/else/else if provide all the functionality you need.
I recommend putting the code you need to run inside that if statement in a separate method and then calling it from the if statement.
if (a.count <= 0) {
nameOfNewMethod();
}
//somewhere else
- (void) nameOfNewMethod {
//code here
}
Put the lines of code you want to "goto" in a function (or if appropriate, a block) and call the function (or block). If there are lines of code you want to skip, you can always return early out of a function, or use an else block?
There is in fact a goto command in Objective-C. To utilize it, you have to create a label, ex:
marker:
and jump to it like so within the same method:
goto marker;
But you can't declare any variables between those two commands. All the variables have to be created before the jump so that they still exist after.
Here's an example of how to use goto:
int x = 0;
if (a.count <= 0) {
goto marker;
}
x = 5;
marker:; // <-- semi-colon indicates the label is followed by an empty statement, thus allowing for immediate variable declaration
int y = x + 7;
In that case, if a.count <= 0, y == 7, else y == 12.

Selection a bool through randomizer

I have a total of 6 booleans and the only thing separating them is a number. They're named checker0 though 5.
So checker0, checker1, checker2, checker3, checker4 and checker5.
All of these grants or denies access to certain parts of the app wether the bool is true or false.
I then have a randomiser using:
randomQuestionNumber = arc4random_uniform(5);
So say we get number 3, checker3 = true;
But my question now is would it be possible to set this one to true without having to go thru if statements.
My idea was to implement the way you print a int to say the NSLog using the %d.
NSLog(#"The number is: %d", randomQuestionNumber);
So something like:
checker%d, randomQuestionNumber = true.
Would something like that be possible? So i won't have to do like this:
if (randomQuestionNumber == 0) {
checker0 = true;
}
else if (randomQuestionNumber == 1)
{
checker1 = true;
}
Thanks you very much! :)
Every time you find yourself in a situation when you name three or more variables checkerN you know with a high degree of probability that you've missed a place in code where you should have declared an array. This becomes especially apparent when you need to choose one of N based on an integer index.
The best solution would be to change the declaration to checker[6], and using an index instead of changing the name. If this is not possible for some reason, you could still make an array of pointers, and use it to make modifications to your values, like this:
BOOL *ptrChecker[] = {&checker0, &checker1, &checker2, ...};
...
*ptrChecker[randomQuestionNumber] = true;

Why generate YES and NO via conditional operator vs. using condition directly?

In Cocoa's NSRange.h, I noticed the following inline function:
NS_INLINE BOOL NSLocationInRange(NSUInteger loc, NSRange range) {
return (!(loc < range.location) && (loc - range.location) < range.length) ? YES : NO;
}
I found it rather perplexing that the author chose to return YES and NO via a conditional operator instead of writing the function like:
NS_INLINE BOOL NSLocationInRange(NSUInteger loc, NSRange range) {
return (!(loc < range.location) && (loc - range.location) < range.length);
}
Is there any reason why the former is preferable? I normally would consider this to just be a quirky programming style, but wondered (possibly erroneously) if there was something I'm missing since it's in one of Apple's public .h files...
It is just poor programming style/understanding. Don't do it.
It is often seen in the work of students who don't properly understand that booleans are values (as they are not numbers and they equate values with numbers) and expressions can be boolean valued.
Note: The boolean/logical operators in (Objective-)C(++) are defined to return integers rather than booleans, so some confusion over booleans is understandable in these languages. However the integers are either 0 or 1 and correspond to false/NO & true/YES respectively.

MATLAB - Dependent properties and calculation

Suppose I have the following class which calculates the solution to the quadratic equation:
classdef MyClass < handle
properties
a
b
c
end
properties (Dependent = true)
x
end
methods
function x = get.x(obj)
discriminant = sqrt(obj.b^2 - 4*obj.a*obj.c);
x(1) = (-obj.b + discriminant)/(2*obj.a);
x(2) = (-obj.b - discriminant)/(2*obj.a);
end
end
end
Now suppose I run the following commands:
>>quadcalc = MyClass;
>>quadcalc.a = 1;
>>quadcalc.b = 4;
>>quadcalc.c = 4;
At this point, quadcalc.x = [-2 -2]. Suppose I call quadcalc.x multiple times without adjusting the other properties, i.e., quadcalc.x = [-2 -2] every single time I ask for this property. Is quadcalc.x recalculated every single time, or will it just "remember" [-2 -2]?
Yes, x is recalculated every single time. This is kind of the point of having a dependent property, since it guarantees that the result in x is always up to date.
If you want to make x a "lazy dependent property", you may want to look at the suggestions in my answer to this question.