4
\$\begingroup\$

This program creates an integer array with a random size of 5-50 elements (inclusive). It then fills the array with random numbers between 0 - 100 (inclusive). The interesting part comes when I then have to print the array as a table limited at 5 columns wide. Also, the array must be centered on an output screen 80 characters wide.

My main concern and question is: how do I efficiently move through an array of an unknown size?

My solution is basically to count through each element, keeping track of how many are left and printing new whole rows while there are still any elements left, and checking each element to see if it should be empty or not.

But would division be possible? My main issue with division is if I were to do rows = NUMBERS / 5 + 1, I would always end up with 1 extra empty row whenever NUMBERS was divisible by 5.

import java.util.Random;

public class NumberGenerator
{
    private static final int MIN_INTS  = 5, MAX_INTS  =  50;    //Range of numbers to be generated
    private static final int MIN_RANGE = 0, MAX_RANGE = 100;    //Legal range of generated numbers

    private static final int TABLE_COLUMNS  =  5;               //Number of columns in output table

    private static Random generator = new Random();             //Random number generator


    /**********************************************************
    * BEGIN Main
    *     Calc number of integers to generate between 5 and 50 (inclusive)
    *     Init array the size of the generated number
    *     Init current number to 0
    *     FOR (each number in array) DO
    *         Assign random number between 0 and 100 to current cell
    *     END FOR
    *     Display title
    *     Display top of table
    *     WHILE (there are numbers not displayed) DO
    *         Display left edge of table
    *         FOR (each cell in table row) DO
    *             IF (numbers are left in the array)
    *                 Display formatted cell value and cell's right edge
    *             ELSE
    *                 Display empty cell and cell's right edge
    *             END IF
    *             Increment current number
    *         END FOR
    *         Display EOL
    *     END WHILE
    *     Display bottom of table
    * END Main
    **********************************************************/
    public static void main (String [] args)
    {
        final int NUMBERS;                                          //Number of integers to generate
        final String BORDER = "+-----------------------------+";    //Top and bottom border
        final String PAD_FORMAT_STR;                                //Printf format for left pad


        int[] numberList;       //Array of generated integers
        int tablePadding = 24;  //Number of columns in front of output table
        int currentNumber;      //Current number drawn in table


        NUMBERS        = generator.nextInt(MAX_INTS - MIN_INTS + 1) + MIN_INTS;
        PAD_FORMAT_STR = "%" + tablePadding + "s%s";
        numberList     = new int[NUMBERS];

        for (int i = 0; i < NUMBERS; i++)
        {
            numberList[i] = generator.nextInt(MAX_RANGE + 1); //+1 to include max bound
        }

        currentNumber = 0;

        System.out.printf("%32s%s", "", "Number Generator\n\n");
        System.out.printf(PAD_FORMAT_STR + "\n", "", BORDER);

        while (currentNumber < NUMBERS)
        {
            System.out.printf(PAD_FORMAT_STR, "", "|");

            for (int i = 0; i < TABLE_COLUMNS; i++)
            {
                if (NUMBERS > currentNumber)
                {
                    System.out.printf(" %3d |", numberList[currentNumber]);
                }
                else
                {
                    System.out.print("     |");
                }

                currentNumber++;
            }

            System.out.println();
        }

        System.out.printf(PAD_FORMAT_STR + "\n", "", BORDER);
    }
}

An example of output is:

                            Number Generator

                    +-----------------------------+
                    |  40 |   3 |  79 |   2 |  37 |
                    |  80 |   2 |  82 |  26 |  89 |
                    |   1 |  88 |  21 |   5 |  45 |
                    | 100 |   5 | 100 |  78 |  94 |
                    |  56 |  31 |     |     |     |
                    +-----------------------------+
\$\endgroup\$
  • 3
    \$\begingroup\$ rows = (NUMBERS + 4) / 5; is the expression you are looking for. Another way would be rows = (NUMBERS / 5) * 5;. \$\endgroup\$ – JS1 Jan 25 '16 at 4:50
  • \$\begingroup\$ @JS1 Perfect, thanks so much!! And then I'd be able to use that in a double loop and calculate the index I need with i * 5 + j - 1 with i counting the rows and j counting the table columns and both starting at 1 instead of 0? \$\endgroup\$ – BrainFRZ Jan 25 '16 at 4:56
3
\$\begingroup\$

Formatting

  • Generally in Java you follow the "Egyptian" bracing style, which opens braces on the line that introduces the block instead of on a separate line:

    public class NumberGenerator {
       // ...
       public static void main (String[] args) {
           //...
       }
    }
    
  • Every declaration should have their own line to facilitate easier reasoning about what variables are declared instead of possibly missing some when skimming over a line initializing two or more

  • SHOUTY_SNAKE_CASE is reserved for constants or static fields. Neither NUMBERS nor BORDER nor PAD_FORMAT_STRING are declared as such.

Commenting

You're significantly overcommenting. Instead of comments at the end of a line you should be using descriptive variable names. You're already doing a good job on that though, so I advise you to just remove most of these comments.

This includes that humungous block comment above main that serves no practical purpose whatsoever. Instead of reading that comment, one can just read the code. That's ad 1) faster and ad 2) guaranteed to describe the actual behaviour of the code.

Unused variables and early declarations.

  • MIN_RANGE is not used. remove it.
  • You seem to be fond of declaring variables up front and then filling them with stuff later on. That makes it hard to follow your initialization logically, since it puts stress on the brain. You need to have each variable in the back of your head and juggle all of them around instead of inspecting each separately and ignoring those that aren't interesting.

Table printing.

It's probably easier to print your table with a nested for loop, since a for-loop allows you to increment two variables in the loop statement.

This makes keeping track of the current row significantly easier for your code.

Final result:

import java.util.Random;

public class NumberGenerator {
    private static final int MIN_INTS = 5;
    private static final int MAX_INTS = 50;
    private static final int MAX_RANGE = 100;

    private static final String BORDER = "+-----------------------------+";
    private static final int TABLE_COLUMNS = 5;

    private static final Random GENERATOR = new Random();

    public static void main(String[] args) {
        final String PAD_FORMAT_STR = "%" + 24 + "s%s";
        int[] numberList = new int[GENERATOR.nextInt(MAX_INTS - MIN_INTS + 1) + MIN_INTS];

        for (int i = 0; i < numberList.length; i++) {
            numberList[i] = GENERATOR.nextInt(MAX_RANGE + 1); //+1 to include max bound
        }

        System.out.printf("%32s%s", "", "Number Generator\n\n");
        System.out.printf(PAD_FORMAT_STR + "\n", "", BORDER);
        for (int i = 0; i < numberList.length; i++) {
            System.out.printf(PAD_FORMAT_STR, "", "|");
            for (int j = 0; j < TABLE_COLUMNS; i++, j++) {
                if (i >= numberList.length) {
                    System.out.print("     |");
                } else {
                    System.out.printf(" %3d |", numberList[i]);
                }
            }
            System.out.println();
        }
        System.out.printf(PAD_FORMAT_STR + "\n", "", BORDER);
    }
}
\$\endgroup\$
  • \$\begingroup\$ The braces formatting is not really as "generally" Egyptian as far as I call tell (without trying to start a holy war here...;) Maven code-style uses next-line braces, as well as Wicket. Lucene tends to uses Egyptian though. \$\endgroup\$ – RobAu Jan 27 '16 at 7:53

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.