7
\$\begingroup\$

I got a four-digit positive number. I need to square the two digits in middle to generate a new number on which the same procedure is applied. The numbers get saved in a list. This loops as long as there isn't an equal number generated (the list contains the number already). If a number is generated containing less than four digits, the code takes the first and middle digit.

  • 1 23 4
  • 23² = 529
  • 52 9
  • 52² = 2704
  • 2 70 4
  • 70² = ...

I've done the core magic within int current = (int) Math.Pow (number % 1000 / 10, 2);. Is this the most elegant way to solve this?

ArrayList<int> numbers = new ArrayList<int> ();

public void generateNumbers (int number) {

    // just in case :) 
    if (number > 9999) {

        throw new ArgumentOutOfRangeException ("Number must be smaller than 10,000");

    }

    // Remove the thousands and get the times 10 fits in (you've only the two numbers in the middle left)
    int current = (int) Math.Pow (number % 1000 / 10, 2);

    // Repeat until an equal number is in the ArrayList
    if (numbers.Contains (current)) {

        return;

    } else {

        numbers.Add (current);
        this.generateNumbers (current);

    }

}
\$\endgroup\$
  • 2
    \$\begingroup\$ I am assuming ArrayList<int> is meant to be List<int>, yes? \$\endgroup\$ – Avner Shahar-Kashtan Aug 10 '16 at 18:12
  • 1
    \$\begingroup\$ What happens if the middle digits are 00 or 02 and what happens if your initial 4 digit number is 0010 ? \$\endgroup\$ – Brad Thomas Aug 10 '16 at 18:32
  • 2
    \$\begingroup\$ @BradThomas When you read 4 digit positive number you should presume that the smallest number is 1000 unless it's pointed that numbers like 0000 are included. And what's the problem if the middle digits are 00 or 02 ? 02 is still 2 and 00 is 0. \$\endgroup\$ – Denis Aug 10 '16 at 18:50
  • 1
    \$\begingroup\$ Have you tried solar power instead of fossil fuels? :P \$\endgroup\$ – immibis Aug 11 '16 at 1:18
  • \$\begingroup\$ (for context, the question title used to be "Is there a more elegant way to power the ...?") \$\endgroup\$ – immibis Aug 11 '16 at 2:49
7
\$\begingroup\$

Some thoughts:

1) I would add a check to ensure that the number being passed in, is positive.

2) You don't need to use the return statement in your first if, in fact the first if does nothing. You could simply add a ! to the if statement and if it passes over it the method will terminate anyway.

// Repeat until an equal number is in the ArrayList
if (!numbers.Contains(current)){
    numbers.Add (current);
    this.generateNumbers(current);
}

3) If you decided to go with a larger number and square using more digits you could potentially run into a StackOverflowException since this uses recursion. I would use a helper method to do the actual calculation which would return a number and instead of an if statement use a while. (Of course if you're checking a cap on the number this could never happen since there can only be 100 numbers that will be added.)

How the code could look:

ArrayList<int> numbers = new ArrayList<int> ();

public void generateNumbers (int number) {

    if (number < 0 || number > 9999) {
        throw new ArgumentOutOfRangeException ("Number must be greater than 0 and less than 10,000");
    }

    // Repeat until an equal number is in the ArrayList
    do  {
        number = helper(number);
        numbers.Add(number);
    } while (!numbers.Contains(number))

}

private int helper(int number) {
    // Remove the thousands and get the times 10 fits in (you've only the two numbers in the middle left)
    return (int) Math.Pow(number % 1000 / 10, 2);

}

Now (with a bit of editing) you could extend the method to take as high of a number as the person wants and always square whats in the middle.

\$\endgroup\$
  • \$\begingroup\$ Omg ... 2 is embarrasing :) Thanks for the answer! \$\endgroup\$ – OddDev Aug 10 '16 at 17:36
  • \$\begingroup\$ Since the the input must be a positive, 4-digit number, the argument check should be number < 1000 || number > 9999. \$\endgroup\$ – Dan Lyons Aug 10 '16 at 17:39
  • \$\begingroup\$ @DanLyons since the solution is recursive and it produces its own numbers that may not be 4 digits it would need to be able to get numbers under 1000 \$\endgroup\$ – yitzih Aug 10 '16 at 17:47
  • \$\begingroup\$ @yitzih fair point, though it looks like the number needs to be at least 3 digits \$\endgroup\$ – Dan Lyons Aug 10 '16 at 17:55
4
\$\begingroup\$

Since you operate with integers, you don't need to call the Math.Pow method. You could replace it with just n * n.
Your core magic will look like:

number = number % 1000 / 10;
int current = number * number;
\$\endgroup\$
  • \$\begingroup\$ It's a maintainability problem the moment you want to expand though. \$\endgroup\$ – Mast Aug 10 '16 at 16:45
  • \$\begingroup\$ Trying to take middle digits of a floating point number doesn't really make sense though (although, in fairness, I don't see the point of this exercise either...) since it brings into question things of precision, if we only consider the mantissa, etc. \$\endgroup\$ – Dannnno Aug 11 '16 at 3:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.