finding the sum of a given Int but ignoring duplicate numbers

Viewed 173

I can't use arrays or lists and I have to use C.

Duplicates mean if you have 975444579 it will show 25 or if you have 32111 it will show 6 and not 8. Here is my code:

#include <stdio.h>

int main() {
    int num = 0, sum = 0, i = 0, oNum = 0, nNum = 0, tNum = 0, e = 0;
    printf("enter a number: ");
    scanf("%d", &num);
    oNum = num;
    while (num != 0) {
        e = 0;
        i = 0;
        nNum = oNum;
        tNum = num % 10;
        do {
            if (nNum % 10 == tNum) {
                i += 1;
            }
            nNum /= 10;
        } while (nNum != 0);
        sum += tNum;
        i -= 1;
        while (e < i) {
            sum -= tNum;
            e += 1;
        }
        num /= 10;
    }
    printf("%d", sum);
    return 0;
}
9 Answers

Not being able to use an array is a silly requirement. It lends itself well to the problem:

Initial:

int seen[10] = { 0 };

Checking if a digit was encountered:

seen[d]

Marking a digit as encountered:

++seen[d];

These could even be combined.

if (!(seen[d]++))
   sum += d;

But, we could use 10 bits of a number in a similar manner.

Initial:

uint16_t seen = 0;

Checking if a bit is set is done as follows:

seen & (1 << d)

Setting a bit is done as follows:

seen |= 1 << d;

finding the sum of a given Int but ignoring duplicate numbers digits?

  1. Form a mask of allowed digits

  2. Iterate once extracting one digit at a time (OP has that part)

  3. If digit not used before, clear that a bit (per digit) and add digit to the sum.

Let us use an unsigned integer to avoid complications with negative values - we'll disallow them.

int digit_sum_no_repeat(unsigned i) {
  int sum = 0;
  unsigned allowed_digits_mask = 0x3FF;  // All 10 digits allowed.
  while (i) {
    unsigned digit = i % 10;  // Extract least significant digit
    unsigned digit_mask = 1u << digit; 
    if (allowed_digits_mask & digit_mask) {
      allowed_digits_mask ^= digit_mask; // clear the bit
      sum += digit;
    }
    i /= 10;
  }
  return sum;
}   
unsigned int n = 1231;
unsigned int nsum = 0;
unsigned int bdigits = 0;
while( n ) {
    bdigits |= 1 << (n%10);
    n /= 10;
    
}
for( unsigned int x = 0; x < 10; x++ ) {
    if( bdigits&(1<<x) ) nsum += x;
}
printf("Sum: %d\n", nsum);

Here's a working example that uses the bits of a single unsigned int to find each digit in a number, and which then adds those found digits:

#include <stdio.h>

int main()
{
    int num = 0, sum = 0, i;
    unsigned int digits = 0u; // MUST be at least 10 bits in size (which is guaranteed)
    printf("enter a number: ");
    scanf("%d", &num);
    while (num != 0) { // first loop - set bits for each digit present:
        int dig = num % 10; // This gets us the value of the lowest digit...
        digits |= (1u << dig); // Set the bit to indicate this digit.
        num /= 10; // .. now remove the lowest digit and 'shift' the others.
    }
    for (i = 1; i < 10; ++i) { // second loop - sum all digits whose corresponding bit is set:
        if (digits & (1u << i)) sum += i;
    }
    printf("%d", sum);
    return 0;
}

It's very hard to follow your program to debug it. You should choose more meaningful variable names or fill the code with all the required comments. Here's a program with better names.

#include <stdio.h>

int main() {
    
    int num, check, copy, digit, notAdupe, sum = 0;
    
    printf("enter a number: ");
    scanf("%d", &num);
    
    for(check = num; check; check /= 10 ) {
        
        digit = check % 10;
        notAdupe = 1;
        
        for(copy = num; copy > check; copy /= 10) {
            
            if( digit ==  copy % 10 ) {
                
                notAdupe = 0;
                break;
            }
        }
        
        if( notAdupe ) sum += digit;
    }
    
    printf("\n%d", sum);
    
    return 0;
}

in this block:

do {
    if (nNum % 10 == tNum)
    {
        i += 1;
    }
    nNum /= 10;
} while (nNum != 0);
i -= 1;

you count how many times tNum appear in the digits that in his left side, so in the number 32111 for example you subtracting the most left 1 twice. you need a way to find out if this the first time for seeing the digit in tNum.you can do it with bitwise of int variable with somethis like this

int flag = 0;
int is_first = 0;
...
tNum = num % 10;
is_first = flag ^ (tNum << 1) > flag;
flag |= (tNum << 1);

the flag will save in his bits which number you already saw for example:

num = 121:
//  you start with
flag = 0
    ...
tNum = 1, flag = 0 so
is_first = 0 ^ (1 << 1) > 0 = 1 > 0('true')
flag = 0 | 1 = 1
    ...
tNum = 2, flag = 1 so
is_first = 1 ^ (2 << 1) > 1 = 3 > 1('true')
flag = 2 | 1 = 3
    ...
tNum = 1, flag = 3 so
is_first = 3 ^ (1 << 1) > 3 = 2 > 3('false')
flag = 3 | 1 = 1

I use switch loop two times ,but the code is so long

#include <stdio.h>

int main() {

int num=0,zero=0,one=0,two=0,three=0,four=0,five=0,six=0,seven=0,eight=0,nine=0,ten=0,s=0;
printf("enter a number: ");
scanf("%d", &num);
while(num != 0)
{
    switch(num%10)
    {
          case 0:
          {
             zero++;
             switch(zero)
             {
                  case 1:
                  {
                      s=s+0;
                  }break;
             }
          }break;
          case 1:
          {
               one++;
               switch(one)
               {
                  case 1:
                  {
                      s=s+1;
                  }break;
               }
          }break;
          case 2:
          {
               two++;
               switch(two)
               {
                  case 1:
                  {
                      s=s+2;
                  }break;
               }
          }break;
          case 3:
          {
               three++;
               switch(three)
               {
                  case 1:
                  {
                      s=s+3;
                  }break;
               }
          }break;
          case 4:
          {
               four++;
               switch(four)
               {
                    case 1:
                    {
                        s=s+4;
                    }break;
               }
          }break;
          case 5:
          {
               five++;
               switch(five)
               {
                  case 1:
                  {
                      s=s+5;
                  }break;
               }
          }break;
          case 6:
          {
               six++;
               switch(six)
               {
                  case 1:
                  {
                      s=s+6;
                  }break;
               }
          }break;
          case 7:
          {
               seven++;
               switch(seven)
               {
                   case 1:
                   {
                       s=s+7;
                   }break;
               }
          }break;
          case 8:
          {
               eight++;
               switch(eight)
               {
                   case 1:
                   {
                       s=s+8;
                   }break;
               }
          }break;
          case 9:
          {
               nine++;
               switch(nine)
               {
                    case 1:
                    {
                        s=s+9;
                    }break;
               }
          }break;
    }
    num /= 10;
}
printf("\nThe sum of the digits exepting repeated value : %d\n",s);
return 0;

}

You can do a trick using files and numbers, without needing to use array as follows:

int main()
{
    int num;
    char c;
    FILE *fp = fopen("temp", "w");
    if(!fp)
    {
        exit(1);
    }
    printf("enter a number: ");
    scanf("%d", &num);
    fprintf(fp, "%d", num);
    fclose(fp);
    
    int mask = 0;
    
    fp = fopen("temp", "r");
    while(fscanf(fp, "%1d", &num) != EOF) // reading 1 digit at a time
    {
        mask |= (1 << num); // here you will set the bit referent to the digit
    }
    fclose(fp);
    int sum = 0;
    for(int i = 1; i < 10; i++)
    {
        if(mask & (1 << i)) // here you check if the bit referent to number i was set
        {
            sum += i;
        }
    }
    printf("sum is %d\n", sum);
}

Another way without the file is:

int main()
{
    int num;
    printf("enter a number: ");
    scanf("%d", &num);
    int mask = 0;
    while(num)
    {
        mask |= (1 << (num%10));
        num = num/10;
    }
    int sum = 0;
    for(int i = 1; i < 10; i++)
        if(mask & (1 << i))
            sum += i;
    printf("sum is %d\n", sum);
}

Here is a much simpler function to compute the sum of unique decimal digits in an integer:

int sum_unique_digits(unsigned n) {
    int sum = 0, bits = 0;
    do {
        bits |= 1 << (n % 10);
    } while (n /= 10);
    do {
        sum += (bits & 1) * n++;
    } while (bits >>= 1);
    return sum;
}
Related