views:

180

answers:

11

Hello, my program generates random numbers with up to 6 digits with

int number = arc4random % 1000000;

I want that my program do something when a number like 66 or 4444 or 77777 appears (multidigit number with all digits identical). I could manual write:

    switch (number) {
    case 11: blabla...;
    case 22: blabla...;
    (...)
    case 999999: blabla;
}

That would cost me many program code. (45 cases...)

Is there an easy way to solve the problem.

+2  A: 

You could figure out how many digits, then divide a six-digit number by 111111, 5-digit number by 11111, etc, and see if the result is an integer.

Excuse me if I don't suggest any Objective-C code, I don't know that language.

pavium
It doesnt work. For example when I devide 976 with 111 the result is 8.79 aka 8, so he automatically jumps to the *multidigit number with all digits identical*-case
Flocked
in a perfect world, it would work, but figuring out the number of digits is going to be almost as painful (if it isn't already a string) and then also requires conversions to floating point numbers and then checking if the result is a whole number (and if you throw in floating point inaccuracy, it will randomly fail)
Grant Peters
@Flocked, I'm sure you can figure out a way to detect that 976/111 is *not* a whole number, therefore 976 is *not* divisible by 111, and is not one of the numbers you're seeking. @Grant, figuring out how many digits shouldn't be too difficult, either, and with a *lot* less than the 45 cases Flocked spoke about in the question. I only provided a rough algorithm. I leave it to the Objective-C experts to implement.
pavium
A: 

Convert to a string and check if each char in the string, starting at position 1, is the same as the previous one.

Tarydon
-1 this is going to be hugely inefficient (speed and memory wise), converting numbers to strings is usually the worst way you could ever go about manipulating them
Grant Peters
How can i convert to Int to a String and how can I check the chars?
Flocked
As Grant has suggested, this would be inefficient. See his much better solution below, which does not involve conversion to a string. As to how to convert an Int to a String, I am not really familiar with Objective-C so I can't help there.
Tarydon
+2  A: 

As long as you use the mod operator (sorry I do not know objective C) but I'm quite certain there must be a mod operator like % and modding it based on 1's.

For instance:

66%11

You know it is the same number of digits because mod returned 0 in this case.

Same here:

7777%1111

JonH
It doesnt work. Before I can do that, I have to know the lenght of the digit, because I can´t use 7777%11 (it returns no 0).I could try every case with a number, but when my number gets for example 143 the %11 returns also 0, even 143 isnt a number with same digits.
Flocked
+1  A: 

You could do this recursively with the divide and multiply operator (a divide with remainder could simplify it though)

e.g.


bool IsNumberValid(int number)
{
    if(number > 10)
    {
        int newNumber = number / 10;
        int difference = number - newNumber * 10;
        number = newNumber;
        do
        {
            newNumber = number / 10;
            if((number - newNumber * 10) != difference)
            {
                // One of the number didn't match the first number, thus its valid
                return true;
            }
            number = newNumber;
        } while(number);
        // all of the numbers were the same, thus its invalid
        return false;
    }
    // number was <= 10, according to your specifications, this should be valid
    return true;
}
Grant Peters
+1  A: 

convert the number to a string, check the length to get the number of digits, then mod by the appropriate number. pseudocode follows where num_to_check is the number you start out with (i.e. 777)

string my_num = (string)num_to_check;
int num_length = my_num.length;
int mod_result;
string mod_num = "1";
int mod_num_int;

for(int i = 1; i < num_length - 1; i++)
{
  mod_num = mod_num + "1";
}

mod_num_int = (int)mod_num;
mod_result = num_to_check % mod_num_int;

//If mod_result == 0, the number was divisible by the appropriate 111... string with no remainder
James Hollingshead
+7  A: 

Here's one way to check that all digits are the same:

bool AllDigitsIdentical(int number)
{
    int lastDigit = number % 10;
    number /= 10;
    while(number > 0)
    {
        int digit = number % 10;
        if(digit != lastDigit)
            return false;
        number /= 10;
    }

    return true;
}
Adam Rosenfield
Thanks I think this is the right way. I just have one problem. When I try to use this the compiler says in line Two at }: "Nested functions are disabled, use -fnested-functions to re-enable". What does this mean?
Flocked
This is another problem, should be addressed in a different question. By the way, how didn't I notice this answer? :) I wrote basically the same thing... 20 minutes later :/
Vinko Vrsalovic
Oh, my sympathies :)
Flocked
+1  A: 

Here's a recursive version, just for larks. Again, not the most efficient way, but probably the shortest codewise.

bool IsNumberValid (int number) {
   if (number < 10) return true;
   int n2 = number / 10; 
   // Check if the last 2 digits are same, and recurse in to check 
   // other digits:
   return ((n2 % 10) == (number % 10)) && IsNumberValid (n2);
}

Actually, this is tail recursion, so a decent compiler ought to generate pretty efficient code.

Tarydon
The recursion will not be that deep so I think it's pretty ok. But looking at it I think it also should be quite easy to rewrite to a loop...
epatel
A: 

Assuming Objective-C has a 'bool' type analogous Standard C99:

#include <assert.h>
#include <stdbool.h>

extern bool all_same_digit(int number);  // Should be in a header!

bool all_same_digit(int number)
{
    static const struct
    {
        int   lo_range;
        int   divisor;
    } control[] =
    {
         { 100000, 111111 },
         {  10000,  11111 },
         {   1000,   1111 },
         {    100,    111 },
         {     10,     11 },
    };
    static const int ncontrols = (sizeof(control)/sizeof(control[0]));
    int i;

    assert(number < 10 * control[0].lo_range);
    for (i = 0; i < ncontrols; i++)
    {
         if (number > control[i].lo_range)
             return(number % control[i].divisor == 0);
    }
    return(false);
}

You can probably work out a variation where the lo_range and divisor are each divided by ten on each iteration, starting at the values in control[0].

Jonathan Leffler
A: 

#include #include

int main() {
    int a = 1111;
    printf("are_all_equal(%d) = %d\n",a,are_all_equal(a));
    a = 143;
    printf("are_all_equal(%d) = %d\n",a,are_all_equal(a));
    a = 1;
    printf("are_all_equal(%d) = %d\n",a,are_all_equal(a));
    a = 101;
    printf("are_all_equal(%d) = %d\n",a,are_all_equal(a));
    return 0;
}

int are_all_equal(int what) {
    int temp = what;
    int remainder = -1;
    int last_digit = -1;
    while (temp > 0) {
        temp = temp/10;
        remainder = temp%10;
        if (last_digit != -1 && remainder != 0) {
            if (last_digit != remainder) return 0;
        }
        last_digit = remainder;
    }
    return 1;
}

Similar, but not exactly equal to the other answers (which I didn't notice were there).

Vinko Vrsalovic
A: 

You might consider looking into a regular expression library (probably overkill for this particular problem, but in general the right solution for pattern matching problems).

jmoreno
A: 
Secure