开发者

How can I get my program to do anything when a "multidigit number with all digits identical" appears?

开发者 https://www.devze.com 2022-12-15 13:06 出处:网络
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 numbe

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.


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


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


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.


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


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


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.


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


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].


#include <stdlib.h>
#include <stdio.h>

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).



digitsequal = ( ((number < 1000000) && (number > 111110) && (number % 111111 == 0)) ||
                ...
                ((number < 1000) && (number > 110) && (number % 111 == 0)) ||
                ((number < 100) && (number > 10) && (number % 11 == 0)) 
              );

Thanks to boolean operations that shortcut, this should be a good enough solution regarding the average number of comparisons, it requires at most only one modulo operation per number, it has no loop, it can be nicely formatted to look symmetric, and it is obvious what it tests. But of course, premature optimization, you know, but since a lot of other solutions are already given... ;)

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号