1

I am working on Consecutive Primes Challenge @ codeeval.com and can't pass the automatic grader. I think i am getting correct results but possibly missing some edge cases. I tried recursion but couldn't get it to work and it was too slow. Figured out another solution with creating two arrays with even and odd numbers. Please let me know if this is a viable solution and if you can see the mistake.

Here is the challenge description:

Alice has an even number of N beads, and each bead has a number from 1 to N painted on it. She would like to make a necklace out of all the beads, with a special requirement: any two beads next to each other on the necklace must sum to a prime number. Alice needs your help to calculate how many ways it is possible to do so.

For example:

N = 4

There are two possible ways to build the necklace. Note that the last bead connects to the first bead.

1 2 3 4
1 4 3 2

Note: The necklace should be unique. For example: 1 2 3 4 is the same as 2 3 4 1 and 3 4 1 2 and 4 1 2 3.

The code has some C and obj-c because of limitation in codeeval.com auto grader. Here is my code:

    BOOL isPrime(int number){
        for(int i = 2;i<(int)(number/2)+1;i++){
            if (number%i == 0) {
                return false;
            }
        }
        return true;
    }

    BOOL isEven(int number)
    {
        if(number%2==0){
            return true;
        }
        return false;
    }


    NSMutableArray *createEvenNumbersArray(int num)
    {
        NSMutableArray *evenNumArray = [[NSMutableArray alloc]initWithCapacity:num];
        for (int i=2; i<=num; i+=2) {
            [evenNumArray addObject:[NSNumber numberWithInt:i]];
        }
        return evenNumArray;
    }

    NSMutableArray *createOddNumbersArray(int num)
    {
        NSMutableArray *oddNumArray = [[NSMutableArray alloc]initWithCapacity:num];
        for (int i=3; i<=num; i+=2) {
            [oddNumArray addObject:[NSNumber numberWithInt:i]];
        }
        return oddNumArray;
    }



    int calculateConsecutive(int input)
    {
        int count = 0;
        BOOL evenFound = NO;
        BOOL oddFound = NO;
        NSMutableArray *oddNumArray = createOddNumbersArray(input); //creates odd number array with all the possiblities
        NSMutableArray *evenNumArray = createEvenNumbersArray(input); // create even number array with all the possibilities
        NSMutableArray *necklace = [[NSMutableArray alloc]init];
        [necklace addObject:[NSNumber numberWithInt:1]]; // start the necklace with 1 to get rid of duplicate necklaces
        for (int i = 2; i<=input; i+=2) { // goes through all the possibilities for the second bit to create the necklase
            NSMutableArray *tempOddNumArray = [oddNumArray mutableCopy]; // populate odd number array
            NSMutableArray *tempEvenNumArray = [evenNumArray mutableCopy]; // puplate even number array
            if(isPrime([[necklace lastObject] intValue] + i)){
                [tempEvenNumArray removeObject:[NSNumber numberWithInt:i]]; //remove number that we added to the necklase
                [necklace addObject:[NSNumber numberWithInt:i]];
                while ([necklace count]<=input) { // start creating the necklace after two numbers were added
                    oddFound = NO;
                    evenFound = NO;
                    for(NSNumber *oddNumber in tempOddNumArray){ // find the odd number possibility from the numbers that are left in the array
                        if(isPrime([[necklace lastObject] intValue] + oddNumber.intValue)){
                            [necklace addObject:oddNumber];
                            oddFound = YES;
                            break;
                        }
                    }
                    if (!oddFound) {
                        break;
                    }else{
                        [tempOddNumArray removeObject:[necklace lastObject]];
                    }
                    for(NSNumber *evenNumber in tempEvenNumArray){ // find the odd number possibility from the numbers that are left in the array
                        if(isPrime([[necklace lastObject] intValue] + evenNumber.intValue)){
                            [necklace addObject:evenNumber];
                            evenFound = YES;
                            break;
                        }
                    }
                    if (!evenFound) {
                        break;
                    }else{
                        [tempEvenNumArray removeObject:[necklace lastObject]];
                    }
                    if (([tempOddNumArray count] == 0) || ([tempEvenNumArray count] == 0) ){
                        break;
                    }

                }
            }
            if (([necklace count] == input) && (isPrime([[necklace lastObject] intValue]+[[necklace firstObject] intValue]))) {
                // check to make sure that the necklace is full and if the sum of the last number and first number is prime
                count= count + 1;
            }
            NSLog(@"%@",necklace);

            [necklace removeAllObjects];
            [necklace addObject:[NSNumber numberWithInt:1]];
        }
        return count;
    }

    -(void)primesMain
    {
        int necklaceCount = 0;
        int input = 18;
        if (isEven(input)) {
            necklaceCount = calculateConsecutive(input);
        }
        NSLog(@"%d",necklaceCount);
    }

-(void)viewDidLoad
{
     [self primesMain];
}

I apologize regarding crossposting with code review site. I wanted to get suggestions on the code and also find the error. Let me know and i will delete the post on one of the forums.

Thank you!

=============== Update

I found the error in my previous code. It really didn't iterate through all the possibilities. Now i rewrote the code using recursion. I am getting different answers but still not correct. Codeeval is usually using 8 is the test value and i get 0 for result. I wonder if that is not correct. Here is the updated code

NSUInteger count=0; // using global variable so that i don't have to deal with counting in recursion for now anyway

BOOL isPrime(int number){
    for(int i = 2;i<(int)(number/2)+1;i++){
        if (number%i == 0) {
            return false;
        }
    }
    return true;
}

BOOL isEven(int number)
{
    if(number%2==0){
        return true;
    }
    return false;
}

void calculateNumNecklaces(int numOfBeads, NSMutableArray *beadsArray, NSMutableArray *necklace)
{

    if ([beadsArray count] == 1) {
        NSLog(@"%@",necklace);

        if((isPrime([[necklace lastObject] intValue] + [[beadsArray lastObject] intValue]) && (isPrime([[necklace objectAtIndex:0] intValue] + [[beadsArray lastObject] intValue])))){
            count +=1;
        }
        //return 1;
    }else{
        int previousNumber = [[necklace lastObject] intValue];
        int startPos = 0;
        if (isEven(previousNumber)){
            if (isEven([[beadsArray objectAtIndex:0] intValue])) {
                startPos = 1; //it will itterate through odd numbers only in the bead array by starting with the position where the odd number is
            }
        }else {
            if (!isEven([[beadsArray objectAtIndex:0] intValue])) {
                startPos = 1; //it will itterate through even numbers only in the bead array by starting with the position where the odd number is
            }
        }
        for (int pos = startPos; pos < [beadsArray count]; pos+=2) {
            if (isPrime(previousNumber  + [[beadsArray objectAtIndex:pos] intValue])) {
                NSMutableArray *tempNecklace = [necklace mutableCopy];
                [tempNecklace addObject:[beadsArray objectAtIndex:pos]];
                NSMutableArray *tempArray = [beadsArray mutableCopy];
                [tempArray removeObjectAtIndex:pos];
                //NSLog(@"%@",necklace);
                calculateNumNecklaces(numOfBeads, tempArray, tempNecklace);
            }
        }

    }


    //return 0;
}



-(void)primesMain
{
    int input = 6;
    if (isEven(input)) {
        NSMutableArray *beadsArray =[[NSMutableArray alloc] init];
        for (int i = 2; i<=input; i++) {
            [beadsArray addObject:[NSNumber numberWithInt:i]];
        }
        NSMutableArray *necklace = [[NSMutableArray alloc]init];
        [necklace addObject:[NSNumber numberWithInt:1]];
        calculateNumNecklaces(input, beadsArray, necklace);
    }
    NSLog(@"%d",count);
}
Yan
  • 3,533
  • 4
  • 24
  • 45
  • 2
    I'm thinking you could turn this into a graph theory problem. That would make solving it easier if you can calculate the number of possible loops based on the number of edges at each vertex. Or something. – Fogmeister Apr 14 '15 at 18:51
  • Not great in math theories. I will check it out. Thanks! – Yan Apr 14 '15 at 19:37
  • I found the error in my code and i updated the answer with a different solution using recursion. Let me know if it make sense. Thanks – Yan Apr 15 '15 at 01:40
  • That's cool. A little more searching on my part and I discovered The Hamiltonian Cycle problem. (A Hamiltonian Cycle is a cycle on a graph that goes to every vertex once (i.e. your necklace beads)). However, the problem is NP-complete and so finding whether they exist is very very slow. At least thats what a small amount of searching and skim reading found. I may be wrong though :D – Fogmeister Apr 15 '15 at 07:07

1 Answers1

-1

this program for finding how many possibilities of consecutive numbers(rummy in cards) in an array....

program:

#include<iostream.h>
#include<conio.h>
void main()
   {
      int a[10],j,i,n,c,d;
      cin>>n;
       for(i=1;i<=n;i++)
         {
           cin>>a[i];
         }
 for(i=1;i<=n;i++)
  {
    for(j=1;j<=n-i;j++)
      {
         if(a[j]>a[j+1])
          {
            int temp;
            temp=a[j];
            a[j]=a[j+1];
             a[j+1]=temp;
           }
       }
       }
   for(j=1;j<=n;j++)
    {
      c=a[j]-a[j+1];
      d=a[j]-a[j+2];
          if(c==-1 && d==-2)
            {
                 cout<<a[j]<<a[j+1]<<a[j+2];
               }
          cout<<"\n";
      }
    getch();
   }

      output:
         input:
             a[i]={4,3,6,7,8,5}
         output:
                  345
                  456
                  567
                  678