-1

Hello everyone and thank you for taking your time to answer this very stupid but for me tough question. I have spent so much time trying to figure out how to do this, yet some may find this very simple. The exercise goes like this: "Write the program, that contains a function "numbers", which will print all four-digit numbers which: all digits are odd and do not contain a digit 0." My code is below but if anyone knows how to write a better code than to just correct mine, please share it in the comments.

#include <iostream>

using namespace std;

/* s is the remain when dividing i by 10 */

void numbers ()
{
    for (int i = 9999; i >= 1000; i/=10)
    {
        int s = i % 10;
        if (s % 2 == 1 && s != 0)
        {
            cout << i << endl;

        }
        i/=10;
    }
}


int main()
{
    numbers();
    return 0;
}
Pythonista
  • 19
  • 3
  • 1
    The code doesn't do what it's supposed to, does it? – user253751 Sep 07 '22 at 18:33
  • I know it does not, that is the problem... – Pythonista Sep 07 '22 at 18:35
  • What output does it return – drescherjm Sep 07 '22 at 18:38
  • 2
    Nothing helps debug a program quite like a debugger. Run the program in the debugger. Step through the program line by line, and keep an eye on that the program does. When you see a line deviate from your expectations, like storing the wrong value or taking the wrong path, you have found a bug (Or your expectations are wrong. Fix that, too). Look back, sometimes rerunning the program, to see how the program got into the bad state. If you can't figure out what happened and why, that's when you ask a question on Stack Overflow. If you have no idea what happened, you're asking too early. – user4581301 Sep 07 '22 at 18:38
  • 2
    What do you expect from this `i/=10;` ? – Bo Halim Sep 07 '22 at 18:39
  • You actually have that 2 times each iteration. – drescherjm Sep 07 '22 at 18:40
  • Here's a hint. i/1000&1 & i/100&1 & i/10&1 & i&1 – doug Sep 07 '22 at 18:43
  • I'd go the other way around: generate numbers that meet the requirement. `for (int digit4 = 1000; digit4 < 10000; digit4 += 2000) for (int digit3 = 100; digit3 < 1000; digit3 += 200) /* remainder left as an exercise for the reader */`. – Pete Becker Sep 07 '22 at 18:51
  • 1
    It's easy to see that your code doesn't yield the correct results: During the first iteration you divide `i` by 10 twice resulting in `99`, so there's just one iteration of the `for` loop... – fabian Sep 07 '22 at 18:54
  • 1
    `void numbers() { constexpr char digits[]{'7', '1', '9', '5', '3'}; constexpr auto digitCount = std::size(digits); for (unsigned i = 0; i != digitCount * digitCount * digitCount * digitCount; ++i) { for (unsigned j = 0, num = i; j != 4; ++j, num /= digitCount) { std::cout << digits[num % digitCount]; } std::cout << '\n'; } }` Now you only need to be able to explain that code to your instructor ;) (And of course why you printed the number in an order that makes the assignment hard to mark...) – fabian Sep 07 '22 at 19:04
  • ^^^ If you're feeling especially devilish, limit yourself to just one line break at the end; technically there's no requirement to add any whitespace between the numbers... – fabian Sep 07 '22 at 19:07
  • [What is a debugger and how can it help me diagnose problems?](https://stackoverflow.com/questions/25385173/what-is-a-debugger-and-how-can-it-help-me-diagnose-problems) – Jesper Juhl Sep 08 '22 at 03:01

1 Answers1

2

We can approach the problem by analyzing the requirements.

So, we need odd digits. There are only 5 odd digits: 1,3,5,7,9. Any number that we create can consist only of those 5 digits.

The second observation is that there are 5^(NumberOfDigits) different numbers. That is easy to understand. Example: For the first digit, we have 5 possibilities. And then, for each of this 5 digits we have again 5 possible second digits. So, now already 5*5=25 numbers. And for each of the 5 second digits we have again 5 third digits, so, 125 numbers. And for a 4 digit number, we have 5*5*5*5=5^4=625 different numbers.

Good, how to find them? It is obvious, that the delta between two odd digits is 2. Or with other words, if we have an odd digit, we can simply add 2 to get the next odd digit. After the 9, we will have an overflow and need to continue again with 1.

There are many potential designs for the solution.

I will show here an example, were I do not use a complete number, but an array of digits. Then I will add 2 to one digit and if there is an overflow, I will also add 2 to the next digit and so on and so on. Somehow simple.

We do this, until the most significant digit will flip to one, and then all digits are 1 again.

#include <iostream>
#include <array>
#include <algorithm>
#include <iterator>
#include <iomanip>

// Number of digits in a number
constexpr size_t NumberOfDigits = 4u;
// Representation of the number as an array of digits
using Digits = std::array<int, NumberOfDigits>;

// Get the next number/digits
constexpr void nextDigits(Digits& digits) noexcept {

    // Starting at the least significant digit
    for (int i{ NumberOfDigits-1 }; i >= 0; --i) {

        // Get the next odd number
        digits[i] += 2;

        // Check for overflow, then reset to 1, else stop
        if (digits[i] > 9) digits[i] = 1;
        else break;
    }
}
int main() {
    // Define our array with digits and fill it with all one
    Digits d{};
    std::fill(d.begin(), d.end(), 1);

    // Some counter, Just for display purposes
    unsigned long long i = 1;
    do  {
        // Some debug output
        std::cout << std::right << std::setw(30) << i++ << " --> ";
        std::copy(d.begin(), d.end(), std::ostream_iterator<int>(std::cout));
        std::cout << '\n';

        // And, get the next number/digits
        nextDigits(d);

    // Do this, until we have found all numbers
    } while (not std::all_of(d.begin(), d.end(), [](const int i) {return i == 1; }));
}

Again, this is one of many potential solutions

A M
  • 14,694
  • 5
  • 19
  • 44