Search code examples
javaloopsmodulo

How is this "number square" problem done with a modulus operator?


I have come across a very familiar problem doing some exercises and for the life of me cannot figure it out using the intended method -- the modulus % operator -- that accepts (int min, int max) parameters as beginning and end limits.

It is to print the following with a call of numberSquare(1, 5):

12345
23451
34512
45123
51234

I have gotten it to work by essentially creating a manual tracker, though I know this is not the correct approach:

private static void numberSquare(int min, int max)
{   
    int difference = max - min;
    // outside loop
    for(int row = min; row <= max; row++)
    {
        // inside loop
        for(int col = row; col <= row + difference; col++)
        {   
            // is in bounds
            if(col <= max)
                System.out.print(col);
            // not in bounds
            else
                System.out.print(col - difference - 1);
        } // next line
        System.out.println();
    }
}

And my other approach using the operator had the inner loop looking like this:

// is in bounds
if(col <= max)
    System.out.print(col);
// not in bounds
else
    System.out.print(col % max + min);

Which gives me an output of:

|12345|                  |12345|
|23452|                  |23451|
|34523|    instead of    |34512|
|45234|                  |45123|
|52345|                  |51234|

I am really struggling to see how I can do this with the modulus % operator and would love any help/suggestions.

Edit for additional information

I got another version to work, but this one also does not have the % operator...

private static void numberSquare(int min, int max)
{
    // track outside rows
    for(int row = min ; row <= max; row++)
    {
       // track inside columns and the print value
       for(int col = min, value = row; 
               col <= max; col++, value++)
       {
           // reset if the value is too high
           value = (value > max) ? min : value;
           System.out.print(value);
       } 
       // next line
       System.out.println();
    } 
}

Solution

  • Assuming your integer is abcd where each letter is a digit. You can do left cyclic shift by first separating bcd and a

    bcd = abcd % 1000
    a = abcd / 1000 (integer division)
    

    Then, to construct the left cyclic shift from bcd and a

    bcda = bcd * 10 + a
    

    In Java, this is how I would implement it

    void numSquare(int min, int max) {
        long number = 0;
        long div = 1;
        // construct the integer, e.g., 12345, and the corresponding power of tens
        for (long i = max; i >= min; --i) {
            number += i * div;
            div *= 10;
        }
        div /= 10;
        
        // left cyclic shifting the integer and printing
        int nShifts = max - min + 1;
        for (int i = 0; i < nShifts; ++i) {
            System.out.println(number);
            number = (number % div) * 10 + (number / div);
        }
    }
    

    If you want to print digit-by-digit and must use %, the trick is to subtract the column by min to shift the range to [0, max-min], use % to relapse once reaching the maximum, then re-add min to turn it back to normal range, like so

    void numSquare(int min, int max) {
        int len = max - min + 1;
        for (int row = min; row <= max; row++) {
            for (int col = row; col < row + len; col++) {
                System.out.print((col - min) % len + min);
            }
            System.out.println(); // break line when we do a new row
        }
    }
    

    I would advised against this approach if possible because of its many calls to System.out.print, which can add up over time.