在不使用数学运算符的情况下确定数字是否可被3整除

时间:2017-01-20 14:42:48

标签: c recursion

我把这个作业作为家庭作业,我无法弄清楚如何做到这一点:

  

输入是数字1,2和3的字符串   您需要构建一个函数来确定字符串表示的数字是否可以被3整除。

     

规则:

     
      
  • 没有循环。
  •   
  • 数字上没有数学运算(+, - ,*,/,%)。
  •   
  • 使用递归。
  •   
     

提示:如果数字的总和可以被3整除 - 那么数字也是。

我尝试使用提示来提出算法来执行此操作,但它不起作用(如果1和2出现相同的次数,则数字可以被3整除。但是如果数字组成则只有1或2它仍然可以被整除,我们再次遇到同样的问题)。

有什么想法吗?

6 个答案:

答案 0 :(得分:3)

嗯,你有多傻吗?入口点是divBy3_0,只需用字符串调用它。

bool divBy3_0(char const *n);
bool divBy3_1(char const *n);
bool divBy3_2(char const *n);

bool divBy3_0(char const *n) {
    switch(*n) {
        case '1': return divBy3_1(&n[1]);
        case '2': return divBy3_2(&n[1]);
        case '3': return divBy3_0(&n[1]);
    }

    return true;
}

bool divBy3_1(char const *n) {
    switch(*n) {
        case '1': return divBy3_2(&n[1]);
        case '2': return divBy3_0(&n[1]);
        case '3': return divBy3_1(&n[1]);
    }

    return false;
}

bool divBy3_2(char const *n) {
    switch(*n) {
        case '1': return divBy3_0(&n[1]);
        case '2': return divBy3_1(&n[1]);
        case '3': return divBy3_2(&n[1]);
    }

    return false;
}

See it live on Coliru

答案 1 :(得分:2)

基于递归和二进制加法(不含+-/*%

  1. 递归地对输入(sum_str_digits
  2. 中的数字求和
  3. 检查是否可以通过3(is_dividable_by_3)分割:

    • 如果数字等于3或6或9则返回1(真)
    • 如果number等于2,4,5,7,8或0则返回0(false)
    • 否则转到1)与总和
  4. 示例代码,当然需要小心(特别是错误处理)

    #include <stdio.h>
    #include <stdlib.h>
    
    
    int badd(int n1, int n2){
        int carry, sum;
        carry = (n1 & n2) << 1;
        sum = n1 ^ n2;
        if (sum & carry)
            return badd(sum, carry);
        else
            return sum ^ carry;
    }
    
    char * int_to_str(int n) {
        //int length_0 = snprintf( NULL, 0, "%d", n) + 1;
        int length_0 = 32;
        char* str = malloc(length_0);
        snprintf( str, length_0, "%d", n);
        return str;
    }
    
    int digit_to_int(char d) {
        char str[2];
    
        str[0] = d;
        str[1] = '\0';
        return (int) strtol(str, NULL, 10);
    }
    
    int sum_str_digits(char * s, int sum){
        sum = badd(sum, digit_to_int(s[0])); 
        if (s[1] == '\0') {
            printf("Sum: %d \n", sum);
            return sum; 
        }
        return sum_str_digits(&(s[1]), sum);;
    }
    
    int is_dividable_by_3(int n) {
        switch (n) {
            case 3:
            case 6:
            case 9:
                return 1;
            case 1:
            case 2:
            case 4:
            case 5:
            case 7:
            case 8:
            case 0:
                return 0;
            default: {
                char * str = int_to_str(n);
                int x = sum_str_digits(str, 0);
                free(str);
                return is_dividable_by_3(x);
            }
        }
    }
    
    
    int main(int argc, char *argv[]){
        int sum;
        sum = sum_str_digits(argv[1], 0);
        printf("Is div by 3: %d \n", is_dividable_by_3(sum));
    
        return 0;
    }
    

    发布时间编辑 - 以前的版本

    在二进制模式下递归减去3(不使用任何被禁止的数学运算符),直到等于3或更小:

    int badd(int n1, int n2){
        int carry, sum;
        carry = (n1 & n2) << 1; // Find bits that are used for carry
        sum = n1 ^ n2; // Add each bit, discard carry.
        if (sum & carry) // If bits match, add current sum and carry.
            return badd(sum, carry);
        else
            return sum ^ carry; // Return the sum.
    }
    
    int bsub(int n1, int n2){
        // Add two's complement and return.
        return badd(n1, badd(~n2, 1));
    }
    int idiv3(int n) {
        if (n == 3) {
           return 1;
        }
        if (n < 3) {
           return 0;
        }
        if (n > 3) {
            return idiv3(bsub(n, 3));
        }
    }
    
    int div3(const char *n) {
       return idiv3(strtol(n, (char **) NULL, 10));
    }
    

答案 2 :(得分:1)

这个应该有效。它通过从3开始循环到数字来代替从数字中连续减去3,保持循环计数器并递归调用自身。 count++ 确实使用了某些&#34; +&#34;字符,但不是&#34; +&#34;操作员而不是数字:

int f(int num){
   int count = 0, i;
   if(num == 3){
      puts ("number is divisible by 3");
   }
   else if(num < 3){
      puts ("number is not divisible");
   }
   else{
      for (i = 3; i < num; i++){
         count++;
      }
      num = count;
      f (num);
   }
}

void g (char *s) {
   f (atoi (s));
}

典型的&#34;编写程序而不编写程序&#34;分配。我有点害怕你从实用编程中学到很多东西。 (除了如何使用只允许使用该语言子集的愚蠢程序来浪费计算资源。)

答案 3 :(得分:0)

我认为只要使用递归构建的总和,就允许对sum进行模数操作。它可能如下所示:

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

int isDividableBy3_recursive(const char* n, int sum) {

    if (!n || !*n) {
        return (sum % 3 == 0) ? 1 : 0;
    }
    else {
        return isDividableBy3_recursive(n+1, sum+(*n - '0'));
    }
}


int isDividableBy3(const char* n) {

    return isDividableBy3_recursive(n,0);
}



int main(int argc, char *argv[]){

    char* testNumbers[] = { "100", "233", "345", "3", "", NULL };

    for (int i=0;testNumbers[i]!=NULL;i++) {
        char* testNumber = testNumbers[i];
        printf("%s dividable by 3:%d\n", testNumber, isDividableBy3(testNumber));
    }

    return 0;
}

答案 4 :(得分:0)

这里的问题是,计算机完成的所有事情都是数学运算。所以我提交一个编译器应该优化的跳转表。这是&#34; Olafesque兼容&#34;溶液

switch (the_damn_number)
{
    case 0:
        return true;
    case 1: case 2:
        return false;
    case 3:
        return true;
        // and so on
    case largest_number_I_care_about:
       // ToDo
}

(如果您不允许将字符串转换为if种类型,请使用switch块。)

使用您喜欢的脚本工具为您生成代码。

答案 5 :(得分:-1)

这是你怎么做的。

您的第一份工作是使用unsigned long long int strtoull(const char *nptr, char **endptr, int base);将字符串转换为unsigned long long。然后将其应用于

bool is_divisible_by_3(unsigned long long n)
{
    if (n > 9){
        // more than one digit
        return is_divisible_by_3(sum_digits_in_number(n));
    } else {
         return n == 0 || n == 3 || n == 6 || n == 9;
    }
}

您需要构建sum_digits_in_number(unsigned long long):如果不使用+/%,在这里&#39,您很难看到如何做到这一点;否则就是一种方式:

sum = 0;
while (n) {
    sum += n % 10;
    n /= 10;
}