Check if any values have changed a certain amount - objective-c

Does anyone know any efficient ways to check if any set of integers contains an integer that has changed by a certain amount.
For example I have:
int1 = 10;
int2 = 20;
int3 = 30;
And I want to know if any of these 3 integers change by 30
Now if int1 becomes 40 than the call should be triggered. At first I thought of just doing something like this.
if (abs((int1+int2+int3)-(newInt1+newInt2+newInt3)) >= 30) {
But many problems can arise from this...
False triggers (e.g. each new int value increases by 10, making the NET change greater than 30 but not necessarily any individual int greater than 30)
Untriggered reactions (e.g. one of the new integer values has increased by 50 so it should be called but then another new integer value is decreased by 50 (again, it should be called) but the net change is now zero because -50+50=0)
Does anyone have any efficient way of doing this? (Yes, I know obviously I could just check each value individually with OR statements...)
So far this is my best stab at it
if ((((abs(int1-newInt1))>=30)+((abs(int2-newInt2))>=30)+((abs(int3-newInt3))>=30))>0) {
But that's basically the same as using an OR statement (probably even takes a little longer than an OR statment.

I don't think that you can get any faster than that, and unless you're dealing with hundreds of millions of integers, this should not introduce a significant performance penalty.
However, you might want to be "clever". What if you somehow "checksum" the two sums? For example, multiply all the old and new numbers with the nth prime, then check if the difference of the new and old sum divided by the indexth prime is the amount you want.
int sum(int arr[], size_t n)
{
int n = 0;
for (int i = 0; i < n; i++)
n += primes[i] * arr[i];
return n;
}
int primes[3] = { 2, 3, 5 }; // or more
int olds[3] = { 10, 20, 30 };
int news[3] = { 40, 20, 30 };
int nth = 0; // check first
int change_expected = 30;
int oldsum = sum(olds, 3);
int newsum = sum(news, 3);
if ((newsum - oldsum) / primes[nth] == change_expected) {
// 1st value changed as expected
}
Note that this will take way more time and CPU cycles that your naive approach.

Since you are using objective-c, you can always create an object that does exactly what you want (see class below the example). The main benefit of doing it this way is that you don't have to check every integer every time one is set. You simply check each number as it is changed to see if it has changed too much.
Usage Example:
// myNumbers.confined will be true until you create a number, and THEN change it by 30 or more.
ARConfinedNumbers *myNumbers = [ARConfinedNumbers new];
[myNumbers addNumber:10];
[myNumbers addNumber:20];
[myNumbers addNumber:30];
[myNumbers replaceNumberAtIndex:0 withObject:40];
// No longer confined because we have changed 10 to 40
if (!myNumbers.confined)
NSLog(#"Not confined.");
// Reset
[myNumbers setConfined:YES];
Here is the class that I wrote to do this. Note that I used an NSArray, assuming that you were programming for iOS/MacOS but you can replace the NSArray with something else if you aren't using those classes. This should give you a great starting point though.
ARConfinedNumbers.h:
#import <Foundation/Foundation.h>
#interface ARConfinedNumbers : NSObject
// confined is true if the numbers have not been changed by more than 30.
// This can be reset by setting it to YES.
#property (nonatomic, assign) BOOL confined;
// Methods to manipulate the set of numbers
// Add more array-type-methods as needed
- (void)addNumber:(int)number;
- (void)replaceNumberAtIndex:(NSUInteger)index withObject:(int)number;
- (int)numberAtIndex:(NSUInteger)index;
- (NSUInteger)count;
#end
ARConfinedNumbers.m
#import "ARConfinedNumbers.h"
/* Private Methods */
#interface ARConfinedNumbers()
#property (nonatomic, strong) NSMutableArray *numbers;
#end
#implementation ARConfinedNumbers
- (id)init
{
self = [super init];
if (self)
{
_confined = YES;
_numbers = [NSMutableArray new];
}
return self;
}
- (void)addNumber:(int)number
{
[self.numbers addObject:#(number)];
}
- (void)replaceNumberAtIndex:(NSUInteger)index withObject:(int)number
{
if (index < self.numbers.count)
{
if (number)
{
int existingNumber = [self.numbers[index] intValue];
if (abs(existingNumber - number) >= 30)
self.confined = NO;
[self.numbers replaceObjectAtIndex:index withObject:#(number)];
}
}
}
- (int)numberAtIndex:(NSUInteger)index
{
if (index < self.numbers.count)
return [self.numbers[index] intValue];
return 0;
}
- (NSUInteger)count
{
return self.numbers.count;
}
#end

Related

Objective-C source code debug: Thread Error

I cannot seem to solve this problem, im not sure what it is at this point but the tread error wont go away. I cant seem to find what im doing wrong.
This code may be a handful to read (sorry) but its very simple. I'am basically invoking a function from main and passing an array of function values, from there im passing two fractions at a time to a method so it find the LCM(least common multiple) using the denominators and return the value. But a thread error seems to be occurring at the call to the findLCM method from function at the point of where the method is declared.
#interface Fraction: NSObject
#property int numerator, denominator;
-(Fraction *)findLCM:(Fraction *)fraction withXFractions:(int)Xfraction;
#implementation Fraction
-(Fraction *)findLCM:(Fraction *)fraction withXFractions:(int)Xfraction{
int lcmOfFraction = 0;
int a, b;
a = fraction.denominator;
b = self.denominator;
int max =(a>b) ? a : b; // get max value out of the two denominators.
for (int i = 0; i < Xfraction; i++) {
while(1) /* Always true. */
{
if(max%a==0 && max%b==0)
{ lcmOfFraction = max;
break; /* while loop terminates. */
}
++max;
}
}
Fraction *lcmDenominator = [Fraction new];
[lcmDenominator setTo:0 over:max]; //passing just LCM (denominator of 2 fractions)
return lcmDenominator;
}
Fraction *addFraction(Fraction **arrayOfFractions, int arraySize) {
Fraction *LCM = [[Fraction alloc] init];
int lcmOfFractions = 0;
[LCM setTo:0 over:1];
for (int i = 0; i <= arraySize; i++) {
LCM = [LCM findLCM:arrayOfFractions[i] withXFractions:4];
//^gets the LCM (the common denominator)
}
return LCM;
}
int main () {
#autoreleasepool {
[frac1 setTo:2 over:12]; [frac2 setTo:2 over:4];
[frac3 setTo:6 over:8]; [frac4 setTo:8 over:3];
Fraction __autoreleasing *arrayOfFractions[4] = {frac1, frac2, frac3, frac4 };
Fraction *LCMFraction = addFraction(arrayOfFractions, 4);
//common LCM return
}
}
You create no threads in this code. When asking a question like this you should clearly explain what the error is, and what you have tried to find its source. People may then be able to help you.
Some hints/suggestions:
use breakpoints to stop your code during execution to allow you to examine the values of your variables
pay close attention to indexing operations, you are using a C array and those do not do bounds checking
ask whether using a C array here, rather than an NSArray is your best choice. Note there is nothing wrong with using C arrays when appropriate.
__autoreleasing probably doesn't mean what you think it does, it is rare to see this used explicitly in user code.
If you have a specific question when you've got further ask a new question on SO, somebody will probably be able to help you out.
HTH

Create an global array containing floating numbers

I wanted to create 2 global arrays which can be updated during the run of the programme.In each update i add one element to zeroth position and deleted the last number
I created the arrays as....
In the .h file..........
//////////////
#interface Shared : NSObject{
NSMutableArray *x;
NSMutableArray *y;
}
#property (nonatomic,retain) NSMutableArray *x;
#property (nonatomic,retain) NSMutableArray *y;
+(Shared*)sharedInstance;
#end
In .m file
staticShared* sharedInstance;
#implementation Shared
#synthesize x;
#synthesize y;
+(Shared*)sharedInstance
{
if (!sharedInstance) {
sharedInstance=[[Sharedalloc]init];
}
returnsharedInstance;
}
-(Shared*)init
{
self = [superinit];
if(self)
{
x=[[NSMutableArrayalloc] init];
x=[NSMutableArrayarrayWithObjects:#"0",#"0",#"0",#"0",#"0",#"0",#"0",nil];
y=[[NSMutableArrayalloc] init];
y=[NSMutableArrayarrayWithObjects:#"0",#"0",#"0",#"0",#"0",#"0",nil];
}
returnself;
}
#end
Then i used to call them and re,ove and added elements using the following code....
[[shared sharedInstance].y removeLastObject];
[[shared sharedInstance].y insertObject:new_element atIndex:0];
[[shared sharedInstance].x removeLastObject];
[[shared sharedInstance].x insertObject:new_element atIndex:0];
In the mean time i call these values and calculate an arithmetic value using an expression.
This seems to work well. But it seems to be an inefficient way to handle floating point numbers which i store in it. As these arrays creates objects. Is there any easy method that i can create a global array containing specified amount of floating point numbers and update it during the run of the programm(array size is fixed) by deleting the last object, and call them back to do calculation?
Please help me!
EDIT 1
To sir deanWombourne
.................................
I implement as you instructed! Can you please go through this and help me to correct 2 errors i get.
IN the .h file
#interface Shared : NSObject{
#private
float input[7];
float output[6];
}
+(Shared*)sharedInstance;
-(void)addNewInput:(float)input1;
-(float *)input;
-(void)addNewOutput:(float)output1;
-(float *)output;
#end
in .m file............
#implementation Shared
-(id)init{
if((self =[superinit])){
for(int n=0; n<7 ;++n)
input[n]=0.00f;
for(int n=0; n<6 ;++n)
output[n]=0.00f;
}
returnself;
}
-(void)addNewInput:(float)input1{
input[0]=input[1];
input[1]=input[2];
input[2]=input[3];
input[3]=input[4];
input[4]=input[5];
input[5]=input[6];
input[6]=input1;
}
-(float *)input {
returninput;
}
-(void)addNewOutput:(float)output1{
output[0]=output[1];
output[1]=output[2];
output[2]=output[3];
output[3]=output[4];
output[4]=output[5];
input[5]=output1;
}
-(float *)output {
returnoutput;
}
#end
When calling it
float reading= (accel_reading)/(1.165969038*1e5f);
[[SharedsharedInstance] addNewInput:reading];
Problems i get
1. In the implementation, it says incomplete implementation (it's a warning not an error)
2. How can i used a for loop to fill array values or is this way ok?
Major problem i get,
When i call it as shown above, program stops running telling
Terminating application due to uncaught exception 'NSInvalidArgumentException', reason '+[SharedsharedInstance]: unrecognized selector sent to class 0x5780'
Please help me through this...............
Your code Smells (and I mean that in the nicest possible way!)
Using two parallel arrays and keeping in sync is a bad design pattern (and a performance hit in quite a few ways!). Especially as there is already a struct that handles storing an x and y at the same time - CGPoint).
You're solving the 'only objects go in arrays' problem by converting your float' primitives toNSString` objects, which is horrendously inefficient - take a look instead at the NSValue class, it's designed to put native C primitives into an object without expensive parsing operations :)
You might also want to look into malloc (and free etc) and deal with the whole problem at the C level - this will mean no objects at all and would be blindingly fast (at the cost of more complicated code).
Hope this helps, if you have any questions just add a comment to this answer :)
EDIT
If all you want to do is store 4 x and y values, then this is probably the easiest way to do it :
#interface Shared : NSObject {
#private
CGPoint points[4];
}
+(Shared *)sharedInstance;
- (void)addNewPoint:(CGPoint)point;
- (CGPoint *)points;
#end
#implementation
- (id)init {
if ((self = [super init])) {
// Start with 0,0 for all your points
for (int n = 0; n < 4; ++n)
points[n] = CGPointZero;
}
return self;
}
- (void)addNewPoint:(CGPoint)point {
// Just move all the points along one and add the new one to the end
// (yes, this could be done in a loop but there's not that much point for 4 points!)
points[0] = points[1];
points[1] = points[2];
points[2] = points[3];
points[3] = point;
}
- (CGPoint *)points {
return points;
}
#end
This gives you a method addNewPoint that removes the first point and adds the new point to the end of your array.
You also get the method points that returns the 4 points. Use it something like :
// To add a point
CGPoint newPoint = CGPointMake(100, 100);
[[Shared sharedInstance] addNewPoint:newPoint];
// To do something with the points (in this case, NSLog them)
CGPoint *points = [[Shared sharedInstance] points];
for (int n = 0; n < 4; ++n)
NSLog(#" Point %i : %#", n, NSStringFromCGPoint(points[n]));
EDIT #2
From your comments, you need two arrays, one with input data and one with output data. Try something like this :
#interface Shared : NSObject {
float inputs[4];
float outputs[5];
}
...
This will give you two arrays to read/write to - one called inputs and the other called outputs. Access them in pretty much the same way you did the ones in my first edit :
float *inputs = [[Shared sharedInstance] inputs];
for (int n = 0; n < 4; ++n)
NSLog(#" Input %i : %f", n, inputs[n]);
float *outputs = [[Shared sharedInstance] outputs];
for (int n = 0; n < 5; ++n)
NSLog(#" Output %i : %f", n, output[n]);
Would a linked list be overkill for what you're trying to achieve? It's not quite as simple as a static array of floats, but makes the removal of the last object and insertion of the zeroth object reasonably simple and fast.
If you want an array containing a specific number of Objects, you can use NSArray, which is static, opposed to NSMutableArray.
As for the array being Global, just implement a singleton class that contains the 2 arrays and provides the associated methods.
in Globals.h:
#interface Globals : NSObject
+ (Globals *) sharedGlobals;
#end
in Globals.m:
#implementation Globals
static Globals *sharedGlobals = nil;
+ (Globals *) sharedGlobals{
#synchronized(self){
if (sharedGlobals == nil){
sharedGlobals = [[self alloc] init];
}
}
return sharedGlobals;
}
you then can access the arrays (after you implemented them) with the following line:
[[Globals sharedGlobals] getArrayX];
Here is a sketch to get you going.
Your array size is fixed and only contains floating point numbers, start with a C array:
double x[] = {0, 0, 0, 0, 0, 0, 0};
double y[] = {0, 0, 0, 0, 0, 0};
The number of elements in these arrays can be calculated rather than hard-coded:
int xCount = sizeof(x)/sizeof(double);
int yCount = sizeof(y)/sizeof(double);
Now use these arrays as a circular buffer, declare a cursor and initialise:
int xCursor = 0;
The item at the front of the queue is at the cursor:
valueAtFrontOfQueue = x[xCursor]; // get the current front item
To remove the value at front and add a new one to the rear replace the value at the cursor with the new value and increment the cursor:
x[xCursor] = newValueForBackOfQueue; // replace it with new item for back of queue
xCursor = (xCursor + 1) % xCount; // and advance cursor using mod arithmetic to it cycles around
No wrapping doubles as objects, no dynamic allocation at all.
Wrap the above up as you see fit, maybe as a class, and you're done.

Random generator Objective-C

I've declared a static array of integer from 1 to 5 and now want to call randomly each number with each press of a button. I don't want the same number to be called twice.
int randomNumber;
static int size = 5;
int position = arc4random() % size - 1;
randomNumber = usedNumbers[position];
int switcher = usedNumbers[size]; // wrong
usedNumbers[position] = usedNumbers[size];
size--;
usedNumbers[position] = switcher;
Here's what I've done so far. There's a hole in my logic somewhere and I could do with some help. I think it's something to do with the switcher which is trying to hold a number whilst another is being deleted.
If all you want to do is to show a random number every time the button is clicked, here is some code that can help.
But first, the line you use to create the position is wrong. Do this instead:
int position = (arc4random() % 5) + 1; // Creates a random number between 1 and 5.
int position = (arc4random() % 5) - 1; // Creates a random number between -1 and 3.
Second, I'd suggest to use an NSArray or NSMutableArray to hold your data.
I assume that you have a method that is called when you press a button. Inside that method you can simply put something like this:
int size = 5; // You might want to get the size of your array dynamically, with something like [usedNumbers count];
int position = (arc4random() % size) + 1; // Generates a number between 1-5.
NSNumber *randomNumber = [usedNumbers objectAtIndex:position]; // Here is your random number from the array.
So.. If you add the array as an instance variable to your class, your header file would look something like this:
#interface MyViewController : UIViewController
#property (nonatomic, retain) NSMutableArray *usedNumbers;
- (IBAction)buttonWasClicked:(id)sender; // Remember to connect it to your button in Interface Builder.
#end
And your implementation file:
#implementation MyViewController
#synthesize usedNumbers;
- (void)viewDidLoad {
// Initialize your array and add the numbers.
usedNumbers = [[NSMutableArray alloc] init];
[usedNumbers addObject:[NSNumber numberWithInt:4]];
[usedNumbers addObject:[NSNumber numberWithInt:13]];
// Add as many numbers as you'd like.
}
- (IBAction)buttonWasClicked:(id)sender {
int size = [usedNumbers count];
int position = (arc4random() % size); // Generates a number between 0 and 4, instead of 1-5.
// This is because the indexes in the array starts at 0. So when you have 5 elements, the highest index is 4.
NSNumber *randomNumber = [usedNumbers objectAtIndex:position]; // The number chosen by the random index (position).
NSLog(#"Random position: %d", position);
NSLog(#"Number at that position: %#", randomNumber);
}
#end
If you do it like this, a random number will be chosen from the array every time the button is clicked.
Also, remember to release all your objects if you don't have ARC enabled.
PS: There are several other questions here on SO covering this subject. Remember to search before asking.
Update:
To make sure every number is used only once, you can remove it from your array when it is chosen. So the buttonWasClicked: method will be something like this:
- (IBAction)buttonWasClicked:(id)sender {
int size = [usedNumbers count];
if (size > 0) {
int position = (arc4random() % size);
NSNumber *randomNumber = [usedNumbers objectAtIndex:position];
// Do something with your number.
// Finally, remove it from the array:
[usedNumbers removeObjectAtIndex:position];
} else {
// The array is empty.
}
}

Trying to make my objective-c program more efficient; Beginner

#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int number, right_digit;
NSLog(#"Enter your number.");
scanf("%i", &number);
while (number != 0) {
right_digit = number % 10;
if (right_digit <0 && number <10 && number>-10) {
right_digit = -right_digit;
NSLog(#"%i- ", right_digit);
}
else if (right_digit<0) {
right_digit = -right_digit;
NSLog(#"%i", right_digit);
}
else {
NSLog(#"%i", right_digit);
}
number /=10;
}
[pool drain];
return 0;
}
The aforementioned code works insofar as finding the reverse of a number, both negative and positive. If negative, say for example, -1234, the answer is supposed to read 4321-. I have no problems there. I am just learning Objective-C so I understand if this is a basic question and my code is very basic. The problem is I have some repeating code and I'm sure there is a better way to write this. I just wanted to know if someone could give me any insight.
I'd do it this way:
NSInteger number = -12;
NSUInteger inverse = 0;
NSInteger sign = (number >= 0) ? 1 : -1;
number = number * sign;
while (number > 0)
{
inverse = inverse * 10 + (number % 10);
number = number / 10;
}
NSLog(#"%i%#", inverse, (sign == -1) ? #"-" : #"");
Without critiquing the details of the algorithm (I might have done it differently, and I haven't evaluated it for correctness/robustness) I can't see anything that would be regarded as "inefficient".
Necessarily you're going to have to iterate through each digit, and you don't appear to iterate more than necessary. The logic is all (save for the actual output) "scalar" (not-object) integer values, so no unnecessary object creation. At most you might be able to eliminate one or two of the tests in your if statements, but there's little efficiency gain there. And I can't see how using any Cocoa classes might have made it simpler.

objective-c how to call different values based on user selection of class

i am working on a sort of simulator for a game i am designing and am in need of a bit of help. the basic simulator will run from within GNUstep's compiler via dos i suppose is the best way to describe it. The basic idea is this: when the program loads it will ask to select the ID of a unit from a populated list upon selection it references a class and creates a new class and its methods then it asks for a defending unit ID, and follows the similar path of creating that new class and methods. i apologize if my terminology is wrong on methods and such.
in any case so far all that i want to have happen happens. i can call the new units via entry by using cases.
on to the hard part:
#interface Unit1: NSObject { #interface Unit2: NSObject {
int unitType; int unitType;
int attackInfantry; int attackInfantry;
int attackArmored; int attackArmored;
int attackAerial; int attackAerial;
int attackAquatic; int attackAquatic;
int attackHeroic; int attackHeroic;
int attackHP; int attackHP;
int attackBAV; int attackBAV;
int attackBDV; int attackBDV;
} }
-(void) print; -(void) print;
-(void) Stats; -(void) Stats;
#end #end
so heres an example of my interface we have two units here: Next up is the implementation:
#implementation Marine #implementation Speeder
-(void) Stats -(void) Stats
{ {
attackHP = 10; attackHP = 10;
attackBAV = 20; attackBAV = 23;
attackBDV = 10; attackBDV = 10;
unitType = 1; unitType = 2;
attackInfantry = 15; attackInfantry = 23;
attackArmored = 10; attackArmored = 18;
attackAerial = 0; attackAerial = 9;
attackAquatic = 7; attackAquatic = 15;
attackHeroic = 0; attackHeroic = 0;
} }
so heres the plan, what i would like to do is have some way of recognizing the unitType and then selecting the proper attack value. so in this case 1 equals infantry and 2 equals armored. for this example the first unit would be using attackArmored = 10; because the program recognizes that the second unit has unitType = 2; and the second unit would use attackInfantry = 23; for the same reason, it knows that it is attacking an infantry type unit.
im not sure if i have the units set up as properly as they should be, but im building this simulator with the intent on learning as i am new to objective-C and the world of code.
i hope this all made sense and i was able to get my question across...
Seems like both Unit1 (should probably be InfantryUnit) and Unit2 (should probably be SpeederUnit) should have an abstract parent called Unit. All the properties (attackHP, etc) would be defined in Unit.
The -init method of each subclass of Unit would set up the hit points, attack values, etc of that particular unit.
I would also have a method on Unit that goes something like this:
typedef enum {
UnitTypeInfantry = 1,
UnitTypeSpeeder = 2
} UnitType;
+ (Unit *) unitWithType:(UnitType)type {
if (type == UnitTypeInfantry) {
return [[[InfantryUnit alloc] init] autorelease];
} else if (type == UnitTypeSpeeder) {
return [[[SpeederUnit alloc] init] autorelease];
}
return nil;
}
Rather than a bunch of individual attack variables for all the different opponent types, you could make a single variable attackValues that's an NSDictionary. The keys of the dictionary would be the opponent type, and the values would be the attack amounts. (Another possibility would be to use an NSArray indexed by unit type, assuming your types are all small integers, but the key/value approach is more flexible.)
For example,
#interface Unit1: NSObject {
int unitType; // numeric type (1, 2, ...)
NSString *unitTypeName; // "Infantry", "Armored", ...
NSDictionary *attackValues;
...
}
-init {
unitType = UnitTypeInfantry;
unitTypeName = #"Infantry";
// Set attack values for other kinds of units
attackValues = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:15], #"Infantry",
[NSNumber numberWithInt:10], #"Armored",
[NSNumber numberWithInt:0], #"Aerial",
[NSNumber numberWithInt:7], #"Acquatic",
[NSNumber numberWithInt:0], #"Heroic",
nil];
}
Then to get the attack value for a particular opponent type, all you need to do is:
int attack = [[attackValues objectForKey:[opponent unitTypeName]] intValue];
The advantages of using a dictionary-driven design instead of individual properties are:
1) You don't have to write a lot of if statements like:
if (opponent.unitType == 1)
attack = attackInfantry;
else if ((opponent.unitType == 1)
attack = attackArmored;
else if ...
2) If you add a new unit type, you don't need to add a new variable to every other unit type.