Prime Generator not working - objective-c

I want to write a really simple prime app. But i am having some problems with the code below it should generate primes from 0 to 99. But instead it just shows 99.
One problem is that only the last number is displayed. But the other one is that the prime "check" doesn't work. How can I fix those problems.
for (i=0; i<100; i++) {
for (n=2; n<i; n++) {
if (i%n == 0) break;
else primetext.text = [NSString stringWithFormat:#"%i, ", i];
}
}

There were a number of problems, I'll try to explain them
The problem with prime checking was that you had the if-else statement inside of the for loop that iterated through the numbers to check. So if your number wasn't divisible by ANY of the numbers you check it would be registered as prime. It would also be registered n times, where n is the number of times it was found to not be divisible.
All even numbers are not prime (aside from 2), so you can do i+=2 to double your speed
You only need to check up to the square root of a number to see if it's prime.
1 isn't a prime so you don't need to include it (especially because it can make your logic more complex).
You were reassigning the string instead of adding a component to it
You were using %i instead of %d. This can sometimes cause weird errors.
Here is your method revised with these points in mind.
int maxNum = 100;
primetext.text = #"2 "; //Start knowing that 2 is the lowest prime (avoid evaluating evens)
for (i=3; i<=maxNum; i+=2) //Start at 3 and add 2 (avoid 1 and 2 as well as even numbers)
{
bool isPrime = YES; //Assume that i is prime
for (n=2; n<sqrt(i); n++) //Divide by every number up to square root
{
if (i%n == 0) //If evenly divisible by n, not a prime
{
isPrime = NO;
break; //Don't need to check any more factors, so break
}
}
if (isPrime) //If isPrime was never set to NO, i is prime
{
NSString *temp = [NSString stringWithFormat:#"%d ", i];
primetext.text = [primetext.text stringByAppendingString:temp];
}
}
Hope this helps.

You should append the number to primetext.text instead of assigning. Right now it's being reassigned on every iteration.

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;
}

Sudoku Backtracking Algorithm Failure

I'm trying to generate a sudoku board, and although I can generate a solution, I now need to remove squares that a user can then fill in. In order to do this, I'd like to use backtracking to check each time that I remove a square, the board is
1. still solvable and 2. has only one solution.
The Problem
When I test my backtracking algorithm on this board (where the zeroes are empty squares), it returns this solution. Obviously I would prefer not to end up with several 9s in the first row, for example.
My Code
- (BOOL) solveArray: (NSArray*) numArray {
NSMutableArray* board = [numArray mutableCopy];
for (int i=0; i<9; i++) { //make all of the arrays mutable as well (since it's 2D)
[board replaceObjectAtIndex:i withObject:[board[i] mutableCopy]];
}
//if everything is filled in, it's done
if (![self findUnassignedLocation:board]) {
NSLog(#"\n%#", [SudokuBoard sudokuBoardWithArray:board]);
return TRUE;
}
NSArray* poss = [[SudokuBoard sudokuBoardWithArray:board] possibleNumbersForRow:self.arow Col:self.acol];
//if there are no options for a location, this didn't work.
if ([poss count] == 0) {
return FALSE;
}
//otherwise, continue recursively until we find a solution
else {
for (int i=0; i<[poss count]; i++) {
//make a tentative assignment
board[self.arow][self.acol] = poss[i];
//return, if successful, done
if ([self solveArray:board]) {
return TRUE;
}
//if that didn't work, unmake it and retry with other options
board[self.arow][self.acol] = [NSNumber numberWithInt:0];
}
}
return FALSE;
}
Any thoughts on where I might be going wrong?
Each level of recursion needs its own row and column variables. That is, row and column should be inputs to solveArray and outputs of findUnassignedLocation instead of being member variables. As it is, when there is backtracking the row and column of the failed level get reused by the caller.
Given that some assigned locations are being overwritten, maybe findUnassignedLocation also contains an error.
Given that the result is invalid, maybe possibleNumbersForRow also contains an error.

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.

How Do I Add By Two in Objective-C?

In the app that I am making, I am using a segmented button to control adding or subtracting a number by one or two, the only problem is that I dont know how to add/subrtact a number by two based on the method that I use to add or subtract by one. This is the code that I have in my app to add or subtract by one:
int number = 0;
-(IBAction)IncrementNumber:(id)sender {
number++;
[currentNumber setText:[NSString stringWithFormat:#"%d", number]];
}
-(IBAction)DecrementNumber:(id)sender {
number--;
[currentNumber setText:[NSString stringWithFormat:#"%d", number]];
}
Based on this code, how would I go twards adding or subtracting by two or even three?
Or more verbal:
number = number + n;
number = number - n;
(Where n is the number you want to add/substract.)
number += 2;
number -= 2;
Generalization:
number += n;
number -= n;
If you have somewhere else where you are setting the amount for incrementing or decrementing something use that number as n.

pattern recognition in a matrix

I'm not sure I'm giving the right name to this, but anyway I have a matrix that essentially contains 1s or 0s. The matrix is a square matrix, its size can be 3x3, 4x4 or 5x5.
By pattern matching, I mean to find some "shapes" in my matrix such as a line, a T or a U, e.g.:
0 1 0
0 1 0
1 1 1
that matrix contains a T, but it also contains 2 lines! Now if the matrix was a 4x4, the shapes don't increase but they can be positioned at more place obviously, e.g.:
0 0 0 0
1 1 1 0
0 0 1 0
1 1 1 0
That matrix would contain a U (no lines though, this is the exception, lines have the size of the matrix).
Naively since the matrix is pretty small I would have tried all possibilities for each shape I'm wiling to support, but it's not very fun. I cannot figure out any algorithm for this though, and not being able to label this operation properly doesn't help ;) Has anyone got any idea how to would do this "efficiently" ? (efficiently may be a bit of an overstatement considering the size of the matrix, but you know what I mean).
There's some ambiguity in your question. For instance, does:
1 1 1
1 1 1
1 1 1
contain 6 lines, a T, a U, and a bunch of other letters of the alphabet? Or are all letters separated? Your initial question implied that letters could be discovered in overlapping fashion, because the T template contains two lines. Thus, a matrix where all elements were 'on' would contain every possible letter/line in every possible position.
Also, I'm assuming you're only concerned about 90 degree rotations and you wouldn't want to try to find 45-degree offset letters when the matrix sizes get large enough to support it.
In terms of ease-of-implementation, the brute-force approach you're talking about (test every position for all four letter rotations) really wins out, I'd say.
Alternatively, you could get pretty fancy by (warning: vague algorithm descriptions ahead!):
1) Walking along the matrix elements until you found a 1. Then essentially flood-fill from that 1 on a stack and keep track of the direction changes. Then have some sort of rotation-invariant lookup that mapped a set of 'on' pixels to found letters.
2) Use some sort of integral-image or box-filter description to take sums of subsections of the matrix. You could then do lookups on the subsections and map the subsection sums to letter/line values.
3) Since the comments have determined that you're only really looking for 4 shapes, a new approach may be worthwhile. You're only examining 4 shapes (line, cross, T, and U) if I'm not mistaken. Each of them can be in 4 orientations. One quick tip is that you can just run the algorithm 4 times but rotate the underlying matrix by 90 degrees. Then you don't have to adjust for rotation in your algorithm. Also note that the cross only needs to be found in one orientation because it looks identical in all 4 orientations and the line is identical in two orientations. Anyway, you could save yourself some work by searching for the 'hardest' things to match first. Let's say I'm looking for an upright 'U' here:
1 0 1
1 0 1
1 1 1
I start in the top left. Rather than checking to make sure that any pixels are 'off' (or 0), I go to the next place I expect to find an 'on' value (or a 1). Let's say that's the pixel below the top left. I check the middle-left pixel, and indeed it's on. Then I check below that. If you develop a simple rule set for each letter, you can quickly abandon the search for it if you don't have the required values turned 'on'. If you then run the same algorithm 4 times and only search for upright values, I'm not sure you'd be able to do much better than this!
The approaches I've mentioned are just ideas. They may be more trouble than they're worth in terms of efficiency gains, though. And who knows, they may not work at all!
Good luck!
I thought I could contribute with what I ended up doing so here it is, following aardvarkk idea. (objective-c code) I wasn't very pedantic with the array size checks because my matrix is necessarily a square matrix. Also sorry if the code is ugly :D
I made a little class structure for the shapes I want to reconize, they have a list of "directions" which are essentially values of an enum.
-(BOOL)findShape:(NSInteger)size directions:(NSArray*)directions{
NSMutableArray* current = [mgs tokens];
for (int rot = 0; rot < 4; rot++) {
for (int i = 0; i < size; i++) {
for(int j = 0; j < size; j++){
NSInteger value = [[[current objectAtIndex:i] objectAtIndex:j] integerValue];
if(value){
BOOL carryOn = [self iterateThroughDirections:directions i:i j:j tokens:current size:size];
if(carryOn){
return YES;
}
}
}
}
current = [self rotate:current];
}
return NO;
}
-(BOOL) iterateThroughDirections:(NSArray*)directions i:(NSInteger)i j:(NSInteger)j tokens:(NSMutableArray*)tokens size:(NSInteger)size{
BOOL carryOn = YES;
for(int k = 0; k < [directions count] && carryOn; k++){
NSNumber* dir = [directions objectAtIndex:k];
NSInteger d = [dir integerValue];
//move in the direction
switch (d) {
case UP:
if(i > 0){
i--;
}else{
carryOn = NO;
}
break;
case DOWN:
if(i < size-1){
i++;
}else{
carryOn = NO;
}
break;
case LEFT:
if(j > 0){
j--;
}else{
carryOn = NO;
}
break;
case RIGHT:
if(j < size-1){
j++;
}else{
carryOn = NO;
}
break;
default:
NSAssert(NO, #"invalid direction");
break;
}
NSInteger v = [[[tokens objectAtIndex:i] objectAtIndex:j] integerValue];
//now that we moved, check if the token is active, if it's not we're done
if(!v){
carryOn = NO;
break;
}
}
return carryOn;
}
-(NSMutableArray*)rotate:(NSMutableArray*)matrix{
NSInteger w = [matrix count];
NSInteger h = [[matrix objectAtIndex:0] count];
NSMutableArray* rotated = [[NSMutableArray arrayWithCapacity:h] retain];
for (int i = 0; i < h; i++) {
[rotated addObject:[NSMutableArray arrayWithCapacity:w]];
}
for(int i = 0; i < h; ++i){
for(int j = 0; j < w; ++j){
[[rotated objectAtIndex:i] addObject:[[matrix objectAtIndex:j] objectAtIndex:h-i-1]];
}
}
return rotated;
}
This seems to be working well for me! Thanks again for the help!