random BOOLs in an efficient way for cocos2d - objective-c

According to Steffen's post this is an efficient way to generate random BOOLs in cocos2d
+(BOOL) getYesOrNo
{
return (CCRANDOM_0_1() < 0.5f);
}
but how do I set a range for this? (e.g. 0 - 29 is the interval and 5 ones BOOL = NO, 25 ones BOOL = YES )

you can do something like this:
+(BOOL) getYesOrNo
{
int tmp = (arc4random() % 30)+1;
if(tmp % 5 == 0)
return YES;
return NO;
}

You should use arc4random for random number generator.
#include <stdlib.h>
u_int32_t
arc4random(void);
The arc4random() function uses the key stream generator employed by
the arc4 cipher, which uses 8*8 8 bit S-Boxes. The S-Boxes can be
in about (2*1700) states. The arc4random() function returns pseudo-
random numbers in the range of 0 to (2*32)-1, and therefore has twice the range of rand and random.
-(BOOL)foo4random
{
u_int32_t randomNumber = (arc4random() % ((unsigned)RAND_MAX + 1));
if(randomNumber % 5 ==0)
return YES;
return NO;
}
For more information on arc4random type
man arc4random
on terminal.

The following code will generate a random bool value:
-(BOOL) randomBool
{
int tmp = (arc4random() % 10);
if(tmp % 2 == 0)
return YES;
return NO;
}

Related

Find next Aloha Number

I found this problem in one of coding practice sites...Problem goes as below.
A number is said to be an aloha number if it is comprises entirely of 4s and 7s. Below are few examples of Aloha Numbers
4477
47744477
Your program will get an integer number of a non Aloha Number and your output must return the next Aloha number (in the form of string) for that input.
Example 1
Input : 1234
Output: 4444
Example 2
Input : 4472
Output: 4474
Input number represent the integer between 1 and 2*(10^9)
Input number is not Aloha Number
I tried to solve this problem as below..
- (NSString *) nextAlohaNumber:(NSUInteger) number{
// method convertNumberIntoDigit return a array of digits present in input number
NSMutableArray *numberDigits = [self convertNumberIntoDigit:number];
NSUInteger tempNum;
for(int index = 0; index < numberDigits.count; index++){
tempNum = [[numberDigits objectAtIndex:index] intValue];
if(4 != tempNum && 7 != tempNum){
if(4 > tempNum){
[numberDigits replaceObjectAtIndex:index withObject:[NSNumber numberWithInt:4]];
}else if (7 > tempNum){
[numberDigits replaceObjectAtIndex:index withObject:[NSNumber numberWithInt:7]];
}
else if(7 < tempNum){
[numberDigits replaceObjectAtIndex:index withObject:[NSNumber numberWithInt:4]];
int previousIndex = index-1;
int previousNum = [[numberDigits objectAtIndex:previousIndex] integerValue];
if(previousIndex ){
if(4 == previousNum){
[numberDigits replaceObjectAtIndex:previousIndex withObject:[NSNumber numberWithInt:7]];
}
else if(7 == previousNum){
[numberDigits replaceObjectAtIndex:index withObject:[NSNumber numberWithInt:4]];
}
}
}
}
}
return [self numberArrayToStr:numberDigits]; // convert strings with digit in Array
}
But this method doesn't pass all the test cases, for example it fails on input 4478, 790 etc.
Can any one please help me to solve this problem for all inputs with better time and space complexity.
PS: I'm ok with C,C++ code as well.
Thanks in advance.
Despite my comment above, I wondered about the "time and space complexity". It turned out to be trivial; this only takes 3 long integer variables and a single loop over each input digit (which can be incremented by this algorithm to use 1 more digit; and this will not cause an integer overflow).
Starting from the lowest digit, if it's lower than 4 replace it with 4. If it's lower than 7, replace it with 7. For 8 and 9, replace it with 4 and increment the next digit. Repeat until all digits are processed.
The following code returns the number itself for a proper "aloha" number, the next higher if not.
It requires long variables (using more than 32 bits), because the aloha number for the largest allowed input, 2*(10^9), is 4444444444 -- outside the range of a 32-bit integer.
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char **argv)
{
long not_aloha, aloha, digit;
if (argc != 2)
{
printf ("please give an aloha number\n");
return -1;
}
not_aloha = atoi (argv[1]);
printf ("not aloha: %ld\n", not_aloha);
aloha = 0;
digit = 1;
while (not_aloha)
{
if ( (not_aloha % 10) <= 4)
aloha += 4*digit;
else if ( (not_aloha % 10 ) <= 7)
aloha += 7*digit;
else
{
aloha += 4*digit;
not_aloha += 10;
}
digit *= 10;
not_aloha /= 10;
}
printf ("aloha: %ld\n", aloha);
return 0;
}

Project Euler # 10 in Objective C

I'm trying to solve Problem 10 in Project Euler, and while I thought I had it, its saying my answer is incorrect. The question is as follows:
The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.
Find the sum of all the primes below two million.
And my code:
int sum;
#interface Prime : NSObject
-(BOOL)isPrime:(int)arg1;
#end
#implementation Prime
-(BOOL)isPrime:(int)arg1 {
if (arg1 == 1) {
NSLog(#"Given 1");
return NO;
}
for (int i = 2; i < arg1; i++) {
if (arg1 % i == 0) {
return NO;
}
}
sum += arg1;
return YES;
}
#end
int main(int argc, const char * argv[])
{
#autoreleasepool {
Prime* primeObject = [[Prime alloc] init];
for (int i = 0; i < 2000000; i++) {
[primeObject isPrime:i];
}
NSLog(#"Sum of primes is %i", sum);
}
}
This code outputs 'Sum of primes is 1179908154' which Project Euler says is incorrect. Help?
The problem is that the sum does not fit into a 32-bit integer. You should use long long instead.
Just a guess, you should try to:
Initialise the sum variable to 0.
Try not to use a global variable like sum that can be accessed from anywhere, in this case do the sum in the main loop instead of in the isPrime method.
Maybe that'll give you the right answer.
You are using int for getting result, so it is wrong.
I'm using long int instead, that is enough for this case.
Here is my code, and it works fine:
int inputNumber = 2000000;
long int result = 0;
for (int i = 2; i < inputNumber; i++) {
BOOL isPrime = YES;
for (int j = 2; j <= sqrt(i); j++) {
if (i%j==0) {
isPrime = NO;
break;
}
}
if (isPrime) {
result += i;
}
}
Result is: 142913828922

How to generate a random number which is different from the previous one in Objective C [duplicate]

This question already has answers here:
Generating non-repeating random numbers
(5 answers)
Closed 8 years ago.
I have a int i generated from( arc4random() % 4), and then I create a new radon int q from another (arc4random() % 4), I wish q is generated until that is different from i.
For example, if i = 2, q must be 0, 1, 3.
How can I do that? Is there a loop or condition can be applied?
Thanks
int q = (arc4random() % 4);
int i = (arc4random() % 4);
while (q == i) {
q = (arc4random() % 4);
}
Use a while loop and store the previous result.
For example,
int previous = (arc4random() % 4);
int current = (arc4random() % 4);
while(current == previous)
{
current = (arc4random() % 4);
}
As some answers here have stated, arc4random with a while loop, in general, is the right answer, but you likely want to use arc4random_uniform(x), as it avoids modulo bias.
From the docs:
arc4random_uniform() will return a uniformly distributed random number less than upper_bound.
arc4random_uniform() is recommended over constructions like ``arc4random() % upper_bound'' as it
avoids "modulo bias" when the upper bound is not a power of two.
int p = (arc4random() % 4);
int q = (arc4random() % 4);
while (p == q) {
p = (arc4random() % 4);
}
I have found when I need randomness, it's nice to use a protocol so I can have random number generators of different flavors, yet not have to change any code when I change generators. With this approach, you can easily change the characteristic of your RNG.
If you wanted to prevent duplicates until all numbers have been used, you could substitute with a class that shuffled the values, then provided them until they were gone... shuffled again... etc. Of course, that approach only works if you have a small number of possible values. For much larger values a probabilistic approach would be necessary.
You would have this protocol somewhere...
#protocol RandomNumberGenerator <NSObject>
- (uint32_t)randomNumber;
#end
Then you could have this class, which provides a specific implementation of the protocol...
#interface NonRepeatingRandomNumberGenerator : NSObject<RandomNumberGenerator>
- (instancetype)init;
- (instancetype)initWithUpperBound:(uint32_t)upperBound;
- (uint32_t)randomNumber;
#end
#implementation NonRepeatingRandomNumberGenerator {
uint32_t lastNumber_;
uint32_t *upperBound_;
}
- (instancetype)init
{
if (self = [super init]) {
lastNumber_ = arc4random();
upperBound_ = NULL;
}
return self;
}
- (instancetype)initWithUpperBound:(uint32_t)upperBound
{
if (self = [super init]) {
lastNumber_ = arc4random_uniform(upperBound);
upperBound_ = malloc(sizeof(*upperBound_));
*upperBound_ = upperBound;
}
return self;
}
- (void)dealloc
{
free(upperBound_);
}
- (uint32_t)randomNumber
{
uint32_t result;
do {
result = upperBound_ ? arc4random_uniform(*upperBound_) : arc4random();
} while (result != lastNumber_);
lastNumber_ = result;
return result;
}
#end
And then to use, you could make the RNG a property of your class, or make it generally available in some other manner...
self.randomGenerator = [NonRepeatingRandomNumberGenerator initWithUpperBound:4];
Later, wherever you want a random number...
randomNumber = [self.randomGenerator randomNumber];
If you ever decided to change how you wanted the numbers to be generated, you would simply replace the line that creates the RNG.

Objective C calculator displaying scientific notation

So I've coded a calculator in objective C and I've formatted the display in .4g as I wanted only significant digits and 4 decimal places. This works fine :)
What I would like it to do is not display 2.34E+05 etc when it displays a longer number like 234,000. I've allowed it to autosize the text in the label so I know it isn't just that the label is too small.
Is there a piece of code that will make it display the actual number instead of the scientific notation?
Formatting with %f instead of %g won't use standard form.
Have a look at this specification.
Edit 1:
I found this answer to help with the rounding.
-(float) round:(float)num toSignificantFigures:(int)n {
if(num == 0) {
return 0;
}
double d = ceil(log10(num < 0 ? -num: num));
int power = n - (int) d;
double magnitude = pow(10, power);
long shifted = round(num*magnitude);
return shifted/magnitude;
}
I then combined these two options to get:
NSLog(#"%.0f", [self round:number toSignificantFigures:4]);
Edit 2:
What about this:
- (NSString *) floatToString:(float) val {
NSString *ret = [NSString stringWithFormat:#"%.5f", val];
unichar c = [ret characterAtIndex:[ret length] - 1];
while (c == 48 || c == 46) { // 0 or .
ret = [ret substringToIndex:[ret length] - 1];
c = [ret characterAtIndex:[ret length] - 1];
}
return ret;
}
I haven't tested this, but it looks as if it limits decimals to 5, then removes any trailing zeros or decimal points.
[Source]

How can I efficiently select several unique random numbers from 1 to 50, excluding x?

I have 2 numbers which are between 0 and 49. Let's call them x and y. Now I want to get a couple of other numbers which are not x or y, but are also between 0 and 49 (I am using Objective C but this is more of a general theory question I think?).
Method I thought of is:
int a;
int b;
int c;
do {
a = arc4random() % 49;
} while ((a == x) || (a == y));
do {
b = arc4random() % 49;
} while ((b == x) || (b == y) || (b == a));
do {
c = arc4random() % 49;
} while ((c == x) || (c == y) || (c == a) || (c == b));
But it seem kind of bad to me, I don't know, I am just trying to learn to be a better programmer, what would be the most elegant way to do this for best practices?
You can use something called the Fisher-Yates shuffle. It's an efficient algorithm for producing a randomly ordered list of values from some set. You would first exclude N from the list of values from which to get random values, and then perform the shuffle.
You should shuffle an array of numbers (of values [0, ..., 49] in your case; you can also exclude your x and y from that array if you already know their values), then grab the first N values (however many you're seeking) from the shuffled array. That way, all the numbers are randomly of that range, and not "seen before".
I'd do something more along the lines of:
NSMutableSet * invalidNumbers = [NSMutableSet set];
[invalidNumbers addObject:[NSNumber numberWithInt:x]];
[invalidNumbers addObject:[NSNumber numberWithInt:y]];
int nextRandom = -1;
do {
if (nextRandom >= 0) {
[invalidNumbers addObject:[NSNumber numberWithInt:nextRandome]];
}
nextRandom = arc4random() % 49;
} while ([invalidNumbers containsObject:[NSNumber numberWithInt:nextRandom]]);
You could add x, y and the new number to a data structure that you can use as a set and do something like (in pseudo-code; the set structure needs something like push to add values and in for checking membership):
number_of_randoms = 2;
set.push(x);
set.push(y);
for (i = 0; i<number_of_randoms; i++) {
do {
new_random = arc4random() % 49;
} while !set.in(new_random);
set.push(new_random);
}
So if objc has something appropriate, this is easy...[aha, it does, see Dave DeLong's post].
This algorithm makes sense if number_of_randoms is much less than 49; if they are comparable then you should one of the shuffle (aka permutation) ideas.
First, make a set of valid numbers:
// Create a set of all the possible numbers
NSRange range = { 0, 50 };// Assuming you meant [0, 49], not [0, 49)
NSMutableSet *numbers = [NSMutableSet set];
for (NSUInteger i = range.location; i < range.length; i++) {
NSNumber *number = [NSNumber numberWithInt:i];
[numbers addObject:number];
}
// Remove the numbers you already have
NSNumber *x = [NSNumber numberWithInt:(arc4random() % range.length)];
NSNumber *y = [NSNumber numberWithInt:(arc4random() % range.length)];
NSSet *invalidNumbers = [NSSet setWithObjects:x, y, nil];
[numbers minusSet:invalidNumbers];
Then, if you don't need the numbers to be guaranteed to be random, you could use -anyObject and -removeObject to pull out a couple of other numbers. If you do need them to be random, then follow LBushkin's answer, but be careful not to accidentally implement Sattolo's algorithm:
// Shuffle the valid numbers
NSArray *shuffledNumbers = [numbers allObjects];
NSUInteger n = [shuffledNumbers count];
while (n > 1) {
NSUInteger j = arc4random() % n;
n--;
[shuffledNumbers exchangeObjectAtIndex:j withObjectAtIndex:n];
}