pollux552
pollux552

Reputation: 127

C program to find growing numbers in an inverval

First, sorry for my english and if I'm not explaining good enough. I hope the output of my code will help you get the idea what is it about. The problem with it is that , the way I've made it, it will work only for up to 999(3 digit number). I guess there should be a loop that "doesn't care" how much digits there are and just does what it has to be done.

int main(){
int n, m, k, digit1, digit2, digit3, p, a = 0;
do{
    printf("Enter m and n (m < n):\n"); scanf("%d %d", &m, &n);
    if (m < n) {
        break;
    }
    else printf("\Error - m > n! Try again.\n\n");
} while (a == 0);

printf("Output:\n");
for (k = m; k <= n; k++){
    p = k;
    do{
        digit3 = p % 10; //123 % 10 = 3         13%10 = 3 == p/10 +1
        digit1 = p / 100; //123 / 100 = 1
        digit2 = (p / 10) % 10; // (123 /10) = 12%10 = 2 
        if (p > 100){
            if ( digit2 == digit1 + 1 && digit3 == digit2 + 1){
                printf("%d ", k);
            } break;
        }
        if (digit3 == ((p / 10) + 1)) {
            printf("%d ", k);
        } break;
        p = p / 10;
    } while (p > 0);
}
getch();
return 0;
}

Example output:

    Enter m and n (m < n):
    1 999
    Output:
    1 12 23 34 45 56 67 78 89 123 234 345 456 567 678 789

This output is correct and it is what the program has to do. Unfortunately I can't come up with loop to make it work with more than 999. It should output all numbers (in the interval entered by the user) in which each digit is bigger (by 1) than the previous.

Upvotes: 2

Views: 646

Answers (4)

Patrick Bucher
Patrick Bucher

Reputation: 1538

So here's another version based on arithmetic:

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

_Bool only_consecutive_figures(int number)
{
    int figure, last;

    for (last = 0; number > 0; number /= 10) {
        figure = number % 10;
        if ((last != 0 && last != figure + 1) || figure == 0) {
            return false;
        }
        last = figure;
    }

    return true;
}

int main()
{
    int m, n, i;

    puts("Enter m and n (m < n):");
    scanf("%d %d", &m, &n);
    if (m >= n) {
        fprintf(stderr, "m must be smaller than n");
        exit(EXIT_FAILURE);
    }

    puts("Output:");
    for (i = m; i < n; i++) {
        if (only_consecutive_figures(i)) {
            printf("%d ", i);
        }
    }
    putchar('\n');

    return EXIT_SUCCESS;
}

Upvotes: 0

Patrick Bucher
Patrick Bucher

Reputation: 1538

Here's a possible solution to the problem. It works with strings rather than numbers, and thus is less efficient but maybe easier to understand:

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

int main()
{
    int m, n, i, j;
    char buf[20], c, last;
    _Bool ascending;

    puts("Enter m and n (m < n):");
    scanf("%d %d", &m, &n);
    if (m >= n) {
        fprintf(stderr, "m must be smaller than n");
        exit(EXIT_FAILURE);
    }

    puts("Output:");
    for (i = m; i < n; i++) {
        sprintf(buf, "%d", i);
        ascending = true;
        last = 0;
        for (j = 0; buf[j] != 0; j++) {
            c = buf[j];
            if (last != 0 && last != c - 1) {
                ascending = false;
                break;
            } else {
                last = c;
            }
        }
        if (ascending) {
            printf("%d ", i);
        }
    }

    return EXIT_SUCCESS;
}

However, it's output looks slightly different:

Enter m and n (m < n):
1 999
Output:
1 2 3 4 5 6 7 8 9 12 23 34 45 56 67 78 89 123 234 345 456 567 678 789

I wonder what the actual rules are, because the numbers between 2 and 9 are note more or less ascending than 1, aren't they?

And here's the output for a bigger number:

Enter m and n (m < n):
1 10000
Output:
1 2 3 4 5 6 7 8 9 12 23 34 45 56 67 78 89 123 234 345 456 567 678 789 1234 2345 3456 4567 5678 6789

Upvotes: 0

Costantino Grana
Costantino Grana

Reputation: 3418

Here is my take. Divide the problem into parts: you need a function to check if a number is "growing", meaning that every digit in its base 10 representation is the following of the one corresponding to the following power of 10, up to the highest non zero one. (Harder than it looks to express this concept formally).

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

bool growing(unsigned int x) 
{
    //if (x < 10)
    //    return false;
    unsigned int last = x % 10 + 1;
    while (x>0) {
        unsigned int cur = x % 10;
        x /= 10;
        if (cur != last-1)
            return false;
        last = cur;
    }
    return true;
}

int main(void)
{
    unsigned int m = 1;
    unsigned int n = 123456789;

    for (unsigned int i = m; i <= n; ++i) {
        if (growing(i)) {
            printf("%i ", i);
        }
    }
}

You should make up your mind on whether a single digit should be accepted or not. If yes, uncomment the first two lines.

Obviously the highest possible growing number is 123456789.

EDIT: A functionless version which directly moves the function into the for loop:

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

int main(void)
{
    unsigned int m = 1;
    unsigned int n = 123456789;

    for (unsigned int i = m; i <= n; ++i) {
        unsigned int x = i;
        bool growing = true;
        //if (x < 10)
        //    growing = false;
        unsigned int last = x % 10 + 1;
        while (x>0) {
            unsigned int cur = x % 10;
            x /= 10;
            if (cur != last - 1)
                growing = false;
            last = cur;
        }

        if (growing) {
            printf("%i ", i);
        }
    }
}

You can get a slightly faster version with a break after setting growing to false.

Useless rant: I don't understand why people keep teaching I/O before the students can understand basic stuff. Not teaching functions, but writing one (main) without realizing it, and calling others (scanf, printf) without knowing anything about pointers. I'm curious on how the teacher justifies the &.

Upvotes: 2

qwn
qwn

Reputation: 367

You dont need to keep track of all the number of digits at once. All you need to check is that the last digit is one more than the second last

Something like this perhaps

int main(){
int n, m, k, digit1, digit2, digit3, p, a = 0;
do{
    printf("Enter m and n (m < n):\n"); scanf("%d %d", &m, &n);
    if (m < n) {
        break;
    }
    else printf("\Error - m > n! Try again.\n\n");
} while (a == 0);

printf("Output:\n");
k = m;
while(k++ <= n){
    int p = k;
    int flag = 0;
    int num;

    while(p > 10){
        // Get the last digit
        // in case of 123 -> 3
        num = p % 10;
        // Reduce p by 10
        // 123 -> 12
        p = p/10;
        // check 3 == 12%10 + 1
        // if this is correct go back to start of the loop
        // we may have more digits
        if(num  == p % 10 + 1) continue;
        // So the digits dont match, set the flag
        // break out of the loop
        flag = 1;
        break;
    }    
    // Outside the loop check the flag and print
    if(k > 10 && !flag)
        printf("%d ",k);
}
return 0;
}

Upvotes: 2

Related Questions