Strange behavior outcome if-statement - objective-c

I have the following code:
- (NSArray *)checkNormalGameDuelAndMatch:(float)nrDuelQs andNrQPerDuel:(float)nrQPerDuel andNrMatchQ:(float)nrMatchQ andActivePlayer:(float)actPlayerNrQ andInactivePlayer:(float)inactivePlayerNrQ {
NSLog(#"checkNormalGameDuelAndMatch:");
// Check for Matches and Duels to prep for swaps and/or match endings
NSArray *theCheckArray = [[NSArray alloc]init];
NSLog(#"nrDuelQs: %.0f / nrQPerDuel: %.0f", nrDuelQs, nrQPerDuel);
// Check if Match still on
NSLog(#"actPlayerNrQ: %.0f / inactivePlayerNrQ: %.0f / nrMatchQ: %.0f", actPlayerNrQ, inactivePlayerNrQ, nrMatchQ);
if (actPlayerNrQ < nrMatchQ && inactivePlayerNrQ < nrMatchQ) {
// Match is still on
_isMatchStillOn = YES;
// Check if Duel is till on
if (nrDuelQs < nrQPerDuel) {
// Duel is still on
_isDuelStillOn = YES;
NSLog(#"_isDuelStillOn = YES;");
}
else {
_isDuelStillOn = NO;
NSLog(#"_isDuelStillOn = NO;");
}
}
else {
//==MATCH IS OVER==//
_isMatchStillOn = NO;
NSLog(#"MATCH OFF");
}
theCheckArray = #[[NSNumber numberWithBool:_isDuelStillOn], [NSNumber numberWithBool:_isMatchStillOn]];
return theCheckArray;
}
With the following NSLog output, during two loops:
checkNormalGameDuelAndMatch:
nrDuelQs: 4 / nrQPerDuel: 5
actPlayerNrQ: 4 / inactivePlayerNrQ: 0 / nrMatchQ: 5
_isDuelStillOn = YES;
checkNormalGameDuelAndMatch:
nrDuelQs: 5 / nrQPerDuel: 5
actPlayerNrQ: 5 / inactivePlayerNrQ: 0 / nrMatchQ: 5
MATCH OFF
I guess there is something wrong with the If-statement and "&&" as i am not expecting the "MATCH OFF" when it comes.
I guess i am blind as this should not be complicated.

This is very likely happening because the variables are of the type float: even through they both print as 5, one of them may be actually slightly smaller than the other (say, 4.9999999999999999). This could happen because of the way actPlayerNrQ is calculated: for example, if you add 0.1 fifty times, you would not get exactly a 5.
Here is a link to an example (it is in C, but that part of the language is shared with Objective C).
float n = 0;
int i = 0;
for (i = 0 ; i != 25 ; i++, n += 0.2);
printf("%f < 5.000000 : %s", n, n < 5.0 ? "yes":"no");
This prints
5.000000 < 5.000000 : yes
To fix this, you could compare with an epsilon, for example
#define EPSILON 1E-8
// 1E-8 stands for 1*10^-8, or 0.00000001
...
if ((actPlayerNrQ - nrMatchQ) < EPSILON && (inactivePlayerNrQ - nrMatchQ) < EPSILON)
...

Related

Compare two CGSize's to best persentage

Need your help, I have input CGSize (for example): 200x300. And array with other CGSize's = [20x20, 100x100, 150x150, 200x100, 200x250, 300x300...].
Please help me to find best item in array that have best compare percentage (for example its 200x250)...
I tried to use for enumerator, for example:
CGSize inputSize = CGSizeMake(200, 300);
for (int i = 0; i < array.count; i++)
{
CGSize concurentSize = CGSizeZero;
switch (i)
{
case 0:
{
concurentSize.width = 20;
concurentSize.height = 20;
}
and so on...
float differencePercentWidth = ( concurentSize.width / inputSize.width ) * 100.0;
float differencePercentHeight = ( concurentSize.height / inputSize.height ) * 100.0;
if (differencePercentWidth > 90 && differencePercentHeight > 90)
{
// FOUND best CGSize... stop
break.
}
}
But, its not working, it differencePercentWidth/differencePercentHeight can be > 100 =(
I need some of method or function that can compare 2 CGSize's in percent match... For example: size 200x300 is best matches with size 200x250... Something like:
float matchesInPerсent = CGSizeCompare(firstCGSize, secondCGSize);
//matchesInPerсent = 0.6; // in percents
Please help, sorry for my english, if you need more details, please let me know. Thanks.
Try the similar logic to calculate the maximum number in the array, but need to less then one finite value. In this cases calculate maximum percentage average of size.width and size.height, the maximum percentage which is closes to 1 is the winner. If you need the upper value of the 100% as well then you need to insert the logic to take that value below the 100% and run the same logic on those sizes as well.
Here is code which will give you closest percentage size from the array.
/*
sizes : array of the sizes represented in NSValue format
size: The size for which you need closest value.
*/
- (CGSize)bestMatch:(NSArray *)sizes withSize:(CGSize)size {
float bestMatch = 0.0;
CGSize bestMatchSize = CGSizeZero;
for (NSValue *value in sizes) {
float percentage = (value.CGSizeValue.width/size.width + value.CGSizeValue.height/size.height)/2;
//If you need greater then 100% and closes to the size
if (percentage > 1.0) {
percentage = -1*(percentage - 2);
}
if (bestMatch < percentage && percentage < 1) {
bestMatch = percentage;
bestMatchSize = value.CGSizeValue;
}
}
//If you need best match you can return bestMatch which is closest in percentage
return bestMatchSize;
}

SpriteKit Memory Leak

After profiling my app, I appear to have a memory leak somewhere in this method:
- (void) didEvaluateActions {
for (int x = 0; x < self.children.count; x++) {
if ([self.children[x] isKindOfClass:[BallNode class]]) {
BallNode * ball = (BallNode *) self.children[x];
if (abs(ball.physicsBody.velocity.dx) < BALL_MIN_VEL_X) {
ball.physicsBody.velocity = CGVectorMake((ball.physicsBody.velocity.dx < 0 ? -1 : 1) * BALL_MIN_VEL_X, ball.physicsBody.velocity.dy);
}
if (abs(ball.physicsBody.velocity.dx) > BALL_MAX_VEL_X) {
ball.physicsBody.velocity = CGVectorMake((ball.physicsBody.velocity.dx < 0 ? -1 : 1) * BALL_MAX_VEL_X, ball.physicsBody.velocity.dy);
}
if (abs(ball.physicsBody.velocity.dy) < BALL_MIN_VEL_Y) {
ball.physicsBody.velocity = CGVectorMake(ball.physicsBody.velocity.dx, (ball.physicsBody.velocity.dy < 0 ? -1 : 1) * BALL_MIN_VEL_Y);
}
if (abs(ball.physicsBody.velocity.dy) > BALL_MAX_VEL_Y) {
ball.physicsBody.velocity = CGVectorMake(ball.physicsBody.velocity.dx, (ball.physicsBody.velocity.dy < 0 ? -1 : 1) * BALL_MAX_VEL_Y);
}
}
}
}
I'm not seeing where this method could be causing a memory leak. BallNode is not created here, so why is instruments pointing back to this location? How is this method causing a leak?
-Thank in advance
I it doesn't appear that you are doing anything wrong, but if you are pointing the the correct spot in code then I think it has to do with self.children.count
Try
NSUInteger count = self.children.count;
for (NSInteger x = 0; x < count; x++)
{
if ([self.children[x] isKindOfClass:[BallNode class]]) {
BallNode * ball = (BallNode *) self.children[x];
if (abs(ball.physicsBody.velocity.dx) < BALL_MIN_VEL_X) {
ball.physicsBody.velocity = CGVectorMake((ball.physicsBody.velocity.dx < 0 ? -1 : 1) * BALL_MIN_VEL_X, ball.physicsBody.velocity.dy);
}
if (abs(ball.physicsBody.velocity.dx) > BALL_MAX_VEL_X) {
ball.physicsBody.velocity = CGVectorMake((ball.physicsBody.velocity.dx < 0 ? -1 : 1) * BALL_MAX_VEL_X, ball.physicsBody.velocity.dy);
}
if (abs(ball.physicsBody.velocity.dy) < BALL_MIN_VEL_Y) {
ball.physicsBody.velocity = CGVectorMake(ball.physicsBody.velocity.dx, (ball.physicsBody.velocity.dy < 0 ? -1 : 1) * BALL_MIN_VEL_Y);
}
if (abs(ball.physicsBody.velocity.dy) > BALL_MAX_VEL_Y) {
ball.physicsBody.velocity = CGVectorMake(ball.physicsBody.velocity.dx, (ball.physicsBody.velocity.dy < 0 ? -1 : 1) * BALL_MAX_VEL_Y);
}
}
}
The way you have it currently it is trying to evaluate self.children.count every iteration through the loop. This shouldn't cause a leak, but there could be something under the hood preventing it from being released correctly when evaluating it repeatedly.
Also you may want to look at enumerateChildNodesWithName: as a quicker alternative than looking at every child and seeing if it is a BallNode.
Hopefully that is the issue and is easily fixed.
You keep creating more and more instances of your BallNode class. Try adding ball = nil; after your last if statement but honestly I do not know if that will help you.
Either your code logic is wrong or there is other stuff going on which you did not post. Usually it would make sense for you to have an ivar of your ball which you would apply the posted code to.

Distance between point and finite line in objective-c

I've looked up some formulas relating to finding the distance a point and a line. On this page, I used example 14
http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html
I have a method that has turned into this:
+(bool) checkPointNearBetweenPointsWithPointA:(CGPoint)pointA withPointB:(CGPoint)pointB withPointC:(CGPoint)pointC withLimit:(float)limit {
float A = pointB.x - pointA.x;
float B = pointA.y - pointC.y;
float C = pointA.x - pointC.x;
float D = pointB.y - pointA.y;
float dividend = fabs( A * B ) - ( C * D );
float divisor = sqrt(pow(A,2) + pow(D,2));
float distanceBetweenPointAndLine = dividend / divisor;
if(distanceBetweenPointAndLine < limit){
NSLog(#"distanceBetweenPointAndLine = %f",distanceBetweenPointAndLine);
return YES;
}
return NO;
}
The problem is that it still returns YES if I'm passed point B, if the line segment is drawn like B----A. Other screwed up things happen to depending on which angle the line is drawn. Just wondering if I need to consider anything else if testing to see if a point is near a finite line. Most examples I see online deal with lines of infinite length.
try my code below. line is considered to exist between points A & B (regardless of how you draw it B->A or A->B ) and point C is the point in consideration to measure the distance.
+ (bool) checkPointNearBetweenPointsWithPointA:(CGPoint)pointA
withPointB:(CGPoint)pointB
withPointC:(CGPoint)pointC
withLimit:(float)limit
{
CGFloat slopeLine = atan((pointB.y-pointA.y)/(pointB.x-pointA.x) );
CGFloat slopePointToPointA = -1 *atan((pointC.y-pointA.y)/(pointC.x-pointA.x));
CGFloat innerAngle = slopeLine + slopePointToPointA;
CGFloat distanceAC = sqrtf(pow(pointC.y-pointA.y,2) + pow(pointC.x-pointA.x,2));
CGFloat distanceBetweenPointAndLine = fabs(distanceAC * sin(innerAngle));
NSLog(#"distanceBetweenPointAndLine = %f",distanceBetweenPointAndLine);
NSLog(#"is exceeding limit ? %#",distanceBetweenPointAndLine > limit ? #"YES":#"NO");
if(distanceBetweenPointAndLine < limit)
{
return YES;
}
return NO;
}

Checking a series of numbers for consistency

I maintain an array of integers. It is important that at all times the integers in this array are in sequence from 0. For example, if there are 5 integers in the array, their values must be 0, 1, 2, 3, 4 (though in any order).
I would like to design a simple, efficient method that checks this. It will return true if the array contains all positive integers in sequence from 0 to array.count - 1.
I would love to hear some different ideas for handling this!
Or, given the integers [0..N-1] if you raise 2 to the power of each in turn the sum will be -1+2^N. This is not a property that any other set of N integers has.
I offer this as an alternative, making no claim about suitability, performance or efficiency, and I recognise that there will be problems as N gets large.
Basically what you want to test is if your array is a permutation of [0...n-1]. There are easy algorithms for this that are O(n) in both time and memory. See for example this PDF file.
Sometimes I use a very simple check that is O(n) in time and O(1) in memory. It can in theory return false positives, but it is a good way to find most mistakes. It is based on the following facts:
0 + 1 + 2 + ... + n-1 == n * (n-1) / 2
0 + 1² + 2² + ... + (n-1)² == n * (n-1) * (2 * n - 1) / 6
I don't know objective-c, but the code would look like this in C#:
bool IsPermutation(int[] array)
{
long length = array.Length;
long total1 = 0;
long total2 = 0;
for (int i = 0; i<length; i++)
{
total1 += array[i];
total2 += (long)array[i] * array[i];
}
return
2 * total1 == length * (length - 1) &&
6 * total2 == length * (length - 1) * (2 * length - 1);
}
This isn't too different from your itemsSequencedCorrectlyInSet: method, but it uses a mutable index set which will be faster than doing -[NSSet containsObject:]. Probably not an issue until you've got thousands of table rows. Anyway, the key insight here is that the Pigeonhole Principle says if you've got N integers less than N and none is duplicated, then you have each of 0...N-1 exactly once.
-(BOOL)listIsValid:(NSArray*)list
{
NSMutableIndexSet* seen = [NSMutableIndexSet indexSet];
for ( NSNumber* number in list )
{
NSUInteger n = [number unsignedIntegerValue];
if ( n >= [array count] || [seen containsIndex:n] )
return NO;
[seen addIndex:n];
}
return YES;
}
Here's my current implementation (testSet is a set of NSNumbers) -
- (BOOL)itemsSequencedCorrectlyInSet:(NSSet *)testSet{
for (NSInteger i = 0; i < testSet.count; i++) {
if (![testSet containsObject:[NSNumber numberWithInteger:i]]) {
return NO;
}
}
return YES;
}

What's wrong with my pascal's triangle?

I've been looking for some simple coding challenges recently, and discovered about Pascal's triangle (here), and I've tried to generate one myself in C/Objective-C. For those that don't know what it is, that link explains it pretty well.
I'm starting to get oddness after the fourth row, and I just can't figure out why.
My output for 5 iterations currently looks like this:
1
1 1
1 2 1
1 3 3 1
4 6 3 1
It should look like this:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
Here is my code so far. The first loop is just a reset loop (setting all the values to 0). The actual logic happens mostly in the second loop. The third loop is where the values are concatenated and formatted in a string.
I've commented this code much more than I would for myself just to aid readability.
int iterations, i, b, mid, chars, temp;
NSLog(#"Please enter the number of itereations");
scanf("%i",&iterations); // take users input and store it in iterations
// calculate where the first 1 should go.
if (iterations % 2 == 0) mid = (iterations)/2;
else mid = (iterations+1)/2;
chars = iterations*2;
int solutions[iterations][chars];
// reset loop
for (i = 0; i<iterations; i++) {
for (b = 0; b<chars; b++) {
solutions[i][b] = 0;
}
}
solutions[0][mid] = 1; // place the initial 1 in first row
for (int row = 1; row<iterations; row++) {
for (int chi = 0; chi<chars; chi++) {
temp = 0;
if (chi > 0) {
temp += solutions[row-1][chi-1]; // add the one diagonally left
}
if (chi < iterations) {
temp += solutions[row-1][chi+1]; // add the one diagonally right
}
solutions[row][chi] = temp; // set the value
}
}
// printing below...
NSMutableString *result = [[NSMutableString alloc] initWithString:#"\n"];
NSMutableString *rowtmp;
for (i = 0; i<iterations; i++) {
rowtmp = [NSMutableString stringWithString:#""];
for (b = 0; b<chars; b++) {
if (solutions[i][b] != 0) [rowtmp appendFormat:#"%i",solutions[i][b]];
else [rowtmp appendString:#" "]; // replace any 0s with spaces.
}
[result appendFormat:#"%#\n",rowtmp];
}
NSLog(#"%#",result);
[result release];
I have a feeling the problem may be to do with the offset, but I have no idea how to fix it. If anyone can spot where my code is going wrong, that would be great.
It appears (from a brief look) that the original midpoint calculation is incorrect. I think it should simply be:
mid = iterations - 1;
In the example of 5 iterations, the midpoint needs to be at array position 4. Each iteration "moves" one more position to the left. The 2nd iteration (2nd row) would then place a 1 at positions 3 and 5. The 3rd iteration at 2 and 6. The 4th at 1 and 7. And the 5th and last iteration would fill in the 1s at 0 and 8.
Also, the second if statement for the temp addition should be as follows otherwise it reads past the end of the array bounds:
if (chi < iterations - 1) {