Home > Mobile >  find the number of prime numbers, from the digits of a number
find the number of prime numbers, from the digits of a number

Time:12-11

I am stuck in this problem, 2 integers A and B must be entered, and A must be separated into digits with respect to B, example: A:1234 B:2 You must separate 12, 23, 34, and then verify how many prime numbers are between these digits

This is what I was able to do so far, I would appreciate it if you could guide me to know which way to go

#include <stdio.h>

int main() {
    int A, B, i, contador;
    //Introducimos el Numero A y verificamos que sea mayor a 0
    for (i = 0; i != -1; i  ) {
        printf("\nIngrese el numero A :");
        scanf("%d", &A);
        if (A > 0) {
            break;
        }
    }
    //Introducimos el Numero B y verificamos que sea mayor a 0
    for (i = 0; i != -1; i  ) {
        printf("\nIngrese el numero B :");
        scanf("%d", &B);
        if (B > 0) {
            break;
        }       
    }
 
    printf("A\t\tB\t\tCifras\t\tCantidad Primos\n");
    printf("%d\t\t%d", A, B);
 
    return 0;
}

CodePudding user response:

First we can greatly simplify validating input with a while loop for each variable that will loop until it scans in a number successfully and it's greater than zero.

Second, we can convert that input number to a string with sprintf which makes looping over individual chunks easier.

Having isolated substrings representing chunks of digits, strtol can convert them back to ints. Below I have simply printed them, but you could readily store them in an array for further manipulation.

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

int main() {
    int A = 0, B = 0;
    
    while (scanf("%d", &A) != 1 || A <= 0);
    while (scanf("%d", &B) != 1 || B <= 0);
 
    char s[1024];

    sprintf(s, "%d", A);

    for (int i = 0; i < strlen(s) - B   1; i  ) {
        char ss[B 1];
        for (int j = 0; j < B; j  ) {
            ss[j] = s[i   j];
        }
        ss[B] = '\0';

        int n = strtol(ss, NULL, 10);

        printf("%d\n", n);
    }
 
    return 0;
}

CodePudding user response:

There are a number of ways you can approach parsing the input of digits into groups of digits to be checked as prime. A very straight-forward approach is to read the digits into a C-string and then convert the groups of digits desired into integer values. That process can also be done a number of different ways. One instructive way is simply to manually handle grouping the number of desired digits to check and manually converting each group of digits to an integer value to check if prime.

Whenever you are reading input from the user, you are encourage to read a line of input at-a-time to avoid the pitfalls inherent in a formatted-read using scanf() (matching-failures and characters left unread in stdin just waiting to bite you on your next input --> which is the reason for the infinite-loop discussed below your other answer) Reading input with fgets() into a sufficiently sized buffer (character array) ensures are characters are read and nothing remains unread in stdin.

So long as you are not on an embedded system or microcontroller, C provides the constant BUFSIZ which you can use to size your character array, that is sufficient for most inputs you will encounter. In your case two arrays are needed, a separate buffer to hold the digits you will group and convert, and a second general buffer to take the other (B) input with. You can declare your buffers and read the digits with something similar to the following:

#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define MAXDIGITS BUFSIZ

...

int main (void) {
  
  char  buf[MAXDIGITS],       /* general input buffer */
        digits[MAXDIGITS];    /* buffer to hold digits */
  int ndigits = 0;            /* digits to separate and test */
  
  /* read/validate input A */
  fputs ("enter number    : ", stdout);
  if (!fgets (digits, sizeof digits, stdin)) {
    puts ("(user canceled input)");
    return 0;
  }
  digits[strcspn (digits, "\n")] = 0; /* trim trailing '\n' */
...

(note: fgets() reads and includes the '\n' generated by the user pressing Enter. A simple way to remove it is to overwrite the '\n' character with 0 -- the nul-terminating character. strcspn() provides an efficient manner for doing so as shown above)

Since you are reading digits, you will want to check that the input is comprised of all digits. You can write a simple function to check if each character entered isdigit() with the function (or macro) provided in ctype.h, e.g.

/* simple function checks if s is composed of all digits,
 * returns 1 if so, 0 otherwise.
 */
int all_digits (const char *s)
{
  int i = 0;
  
  if (!*s || *s == '\n') {    /* check empty-string or empty-line */
    return 0;
  }
  
  for (; s[i]; i  ) {         /* loop over each digit */
    if (!isdigit((unsigned char)s[i])) {
      break;
    }
  }
  
  return !s[i];               /* end-of-string */
}

If the user input into digits is all-digits, you can proceed to take the second input of the number of digits to group together to check for prime. The approach is the same, read with fgets() into buf and then convert the number to int and validate the number represents a group-size that is possible given the number of digits in digits, e.g.

  if (!all_digits (digits)) {         /* validate input all digits */
    fputs ("error: invalid integer input.\n", stderr);
    return 1;
  }
  
  /* read / validate input B */
  fputs ("combine ndigits : ", stdout);
  if (!fgets (buf, sizeof buf, stdin)) {
    puts ("(user canceled input)");
    return 0;
  }
  /* convert string to int / validate */
  if (sscanf (buf, "%d", &ndigits) != 1) {
    fputs ("error: invalid integer input.\n", stderr);
    return 1;
  }
  /* validate the number of digits to combine is possible */
  if (ndigits <= 0 || (size_t)ndigits > strlen (digits)) {
    fputs ("error: requested combination of digits not possible.\n", 
           stderr);
    return 1;
  }

With both inputs taken and the number of digits ndigits to group validated, you can convert your groups to int and check for prime. A simple manual way to do so is to loop over digits beginning with the index ndigits - 1 and looping ndigits times for each group manually converting the digits to int. Only positive values of the groupings are considered, which reduces the task to:

  /* loop starting at ndigits digit, combine every ndigits digits into int
   * (only positive combinations are considered)
   */
  for (int i = ndigits - 1; digits[i]; i  ) {
    int j = i,          /* index for scanning over digits to separate */
        n = ndigits,    /* copy of number of digits to separate */
        num = 0,        /* separated number */
        mult = 1;       /* digit multiplier */
    
    while (n--) {       /* loop ndigits times */
      num  = mult * (digits[j--] - '0');    /* add mult * value to num */
      mult *= 10;                           /* increment mult by 10 */
    }
    
    printf ("  %*d\n", ndigits, num);       /* (optional) output of num */
    
    /** check if num is prime here **/
  }

That's it. Checking for prime is left to you. The input, grouping and conversion of the group to int can be checked by printing each grouping that would be checked for prime.

Example Use/Output

Putting the code together (a complete source is provided at the end), compiling and running your would get:

$ ./bin/group-digits
enter number    : 1234
combine ndigits : 1
  1
  2
  3
  4

Groupings of two:

$ ./bin/group-digits
enter number    : 1234
combine ndigits : 2
  12
  23
  34

Groupings of three:

$ ./bin/group-digits
enter number    : 1234
combine ndigits : 3
  123
  234

Groupings of four:

$ ./bin/group-digits
enter number    : 1234
combine ndigits : 4
  1234

What about a grouping of five with four-digits?

$ ./bin/group-digits
enter number    : 1234
combine ndigits : 5
error: requested combination of digits not possible.

What about a larger string of digits, that itself exceeds the size of int, but so long as the group-size is within the size of int, there is no reason that wouldn't work:

$ ./bin/group-digits
enter number    : 12345678901234567890
combine ndigits : 4
  1234
  2345
  3456
  4567
  5678
  6789
  7890
  8901
  9012
   123
  1234
  2345
  3456
  4567
  5678
  6789
  7890

(note: 0123 is properly converted to 123 instead of an octal value representing 83)

Complete Source for Example

The complete combined source code for the example for easy reference is:

#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define MAXDIGITS BUFSIZ

/* simple function checks if s is composed of all digits,
 * returns 1 if so, 0 otherwise.
 */
int all_digits (const char *s)
{
  int i = 0;
  
  if (!*s || *s == '\n') {    /* check empty-string or empty-line */
    return 0;
  }
  
  for (; s[i]; i  ) {         /* loop over each digit */
    if (!isdigit((unsigned char)s[i])) {
      break;
    }
  }
  
  return !s[i];               /* end-of-string */
}

int main (void) {
  
  char  buf[MAXDIGITS],       /* general input buffer */
        digits[MAXDIGITS];    /* buffer to hold digits */
  int ndigits = 0;            /* digits to separate and test */
  
  /* read/validate input A */
  fputs ("enter number    : ", stdout);
  if (!fgets (digits, sizeof digits, stdin)) {
    puts ("(user canceled input)");
    return 0;
  }
  digits[strcspn (digits, "\n")] = 0; /* trim trailing '\n' */
  
  if (!all_digits (digits)) {         /* validate input all digits */
    fputs ("error: invalid integer input.\n", stderr);
    return 1;
  }
  
  /* read / validate input B */
  fputs ("combine ndigits : ", stdout);
  if (!fgets (buf, sizeof buf, stdin)) {
    puts ("(user canceled input)");
    return 0;
  }
  /* convert string to int / validate */
  if (sscanf (buf, "%d", &ndigits) != 1) {
    fputs ("error: invalid integer input.\n", stderr);
    return 1;
  }
  /* validate the number of digits to combine is possible */
  if (ndigits <= 0 || (size_t)ndigits > strlen (digits)) {
    fputs ("error: requested combination of digits not possible.\n", 
           stderr);
    return 1;
  }
  
  /* loop starting at ndigits digit, combine every ndigits digits into int
   * (only positive combinations are considered)
   */
  for (int i = ndigits - 1; digits[i]; i  ) {
    int j = i,          /* index for scanning over digits to separate */
        n = ndigits,    /* copy of number of digits to separate */
        num = 0,        /* separated number */
        mult = 1;       /* digit multiplier */
    
    while (n--) {       /* loop ndigits times */
      num  = mult * (digits[j--] - '0');    /* add mult * value to num */
      mult *= 10;                           /* increment mult by 10 */
    }
    
    printf ("  %*d\n", ndigits, num);       /* (optional) output of num */
    
    /** check if num is prime here **/
  }
}

Let me know if you have questions.

CodePudding user response:

There's no need for conversion to/from a string of digits.

You've got the "user input", so far.
The following skips that step, using 2 compile-time int's instead.

int main() {
    int v1 = 1357924680, v2 = 3; // simulate two reasonable values from the user.

    printf( "Using %d and %d as input\n", v1, v2 );

    // calculate the power of 10 that has 'v2' zeros.
    int divisor = 1;
    while( v2-- ) divisor *= 10;

    // from right-to-left, push 2-3-4-... digit values onto a stack
    int stack[32] = { 0 }, spCnt = -1;
    while( v1 > divisor/10 )
        stack[   spCnt ] = v1 % divisor, v1 /= 10;

    // retrieve (in order) pairs of values from the stack.
    for( ; spCnt > 0; spCnt-- ) {
        printf( "%d and %d\n", stack[ spCnt ], stack[ spCnt - 1 ] );
        /* call your function that prints all the primes between these values. */
    }

    return 0;
}
Using 1234567890 and 2 as input
12 and 23
23 and 34
34 and 45
45 and 56
56 and 67
67 and 78
78 and 89
89 and 90
Using 1357924680 and 3 as input
135 and 357
357 and 579
579 and 792
792 and 924
924 and 246
246 and 468
468 and 680
  •  Tags:  
  • c
  • Related