Skip to content

Latest commit

 

History

History
108 lines (88 loc) · 3.31 KB

README.md

File metadata and controls

108 lines (88 loc) · 3.31 KB

TallyCounter

Implements a counter as an array of numbers, like a mechanical counter. Every number can go from zero to Long.MAX_VALUE. Can operate in one of three modes: normal, unique numbers and unique combinations. The normal mode works like mechanical counters: actuating it increments the first (rightmost) number and when a number rolls over, the next number increments. For example, the following code

TallyCounter tallyCounter = new TallyCounter(2, Type.NORMAL, 1);
while (!tallyCounter.overflowFlag) {
    System.out.println(tallyCounter.toReadableString());
    tallyCounter.increment();
}

produces the following output

[0, 0]
[0, 1]
[1, 0]
[1, 1]

The unique numbers mode does not allow numbers with the same value. This is useful, for example, to generate all combinations that can be made where every value represents an unique object. For example, the following code

TallyCounter tallyCounter = new TallyCounter(2, Type.UNIQUE_NUMBERS, 1);
while (!tallyCounter.overflowFlag) {
    System.out.println(tallyCounter.toReadableString());
    tallyCounter.increment();
}

produces the following output

[0, 1]
[1, 0]

The unique combination mode does not allow values that appeared together to appear together again. This is useful, for example, to generate all combination of unique values, regardless of order. For example, the following code

TallyCounter tallyCounter = new TallyCounter(2, Type.UNIQUE_COMBINATION, 1);
while (!tallyCounter.overflowFlag) {
    System.out.println(tallyCounter.toReadableString());
    tallyCounter.increment();
}

produces the following output

[0, 1]

This class is also useful to replace a set of nested for loops, where every for command is replaced by a number, and every value is the value that would be iterated. For example, the following code

for (String c : new String[]{"a", "b"}) {
    for (String b : new String[]{"0", "1"}) {
        for (String a : new String[]{"&", "|"}) {
            System.out.format("[%s, %s, %s]\n", a, b, c);
        }
    }
}

produces the same output as the following code

Map<Long, String> mapA = new HashMap<>();
mapA.put(0l, "&");
mapA.put(1l, "|");
Map<Long, String> mapB = new HashMap<>();
mapB.put(0l, "0");
mapB.put(1l, "1");
Map<Long, String> mapC = new HashMap<>();
mapC.put(0l, "a");
mapC.put(1l, "b");
TallyCounter tallyCounter = new TallyCounter(3, Type.NORMAL, 1);
long array[];
while (!tallyCounter.overflowFlag) {
    array = tallyCounter.getArray();
        System.out.format("[%s, %s, %s]\n",
         mapA.get(array[0]),
         mapB.get(array[1]),
         mapC.get(array[2]));
    tallyCounter.increment();
}

which is

[&, 0, a]
[|, 0, a]
[&, 1, a]
[|, 1, a]
[&, 0, b]
[|, 0, b]
[&, 1, b]
[|, 1, b]

It's more verbose, but the amount of nested loops can be altered programatically, which would require recursive methods otherwise. It makes it easier to implement brute force algorithms and to skip combinations according to the modes mentioned above.

I've created a program here that demonstrates the functionality of this class.

A few words about Maven.