0

I have written this code for a program to create a combination of the the letters aaa to zzz. There are 17,576 combinations. For example first is aaa then aab and so on.

I want my code to count the different combinations such as 1. aaa 2. aab 3. aac and so on during the output.

Here is my code:

for(char c1 = 'a'; c1 <= 'z'; c1++){
        for(char c2 = 'a'; c2 <= 'z'; c2++){
            for(char c3 = 'a'; c3 <= 'z'; c3++){
                System.out.println("" + c1 + c2 + c3);
                }
            } 
        }

Thank you!

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154

4 Answers4

3

Well you could maintain a counter variable which gets incremented at each execution of the inner loop:

int counter = 0;
List<String> combinations = new ArrayList<>();

for (char c1 = 'a'; c1 <= 'z'; c1++) {
    for (char c2 = 'a'; c2 <= 'z'; c2++) {
        for (char c3 = 'a'; c3 <= 'z'; c3++) {
            String combo = "" + c1 + c2 + c3;
            System.out.println(combo);
            combinations.add(combo);
            ++counter;
        }
    } 
}

System.out.println("total number of combinations is " + counter);  // 17576
Tim Biegeleisen
  • 502,043
  • 27
  • 286
  • 360
  • Thanks. How would I be able to store this data in an array list? – creativethoughts Jun 03 '22 at 04:52
  • 1
    @creativethoughts Use its `add` method. – Ole V.V. Jun 03 '22 at 04:57
  • 2
    @creativethoughts actually this is a FAQ platform, that is, to collect questions & answers useful to the community - not just to debug and correct your code - seems like you have not yet completed the [tour] :-/ || also your are asking a different question in comment ("How ... store this data ...") - please do not turn into a [Help Vampire](https://meta.stackoverflow.com/a/258208/16320675) :-) – user16320675 Jun 03 '22 at 07:50
1

Here is an alternative implementation.

IntStream of code points

I recommend making a habit of using code points integer numbers rather than the legacy type char when working with individual characters. As a 16-bit value, a char is physically incapable of representing most characters.

We can generate the range of code points from a to z (97 to 122) from an IntStream. The Character.toString( codePoint ) method generates a single-character String object from our code point integer.

List < String > characters =
        IntStream
                .rangeClosed( "a".codePointAt( 0 ) , "z".codePointAt( 0 ) )  // ( 97 inclusive, 122 inclusive )
                .mapToObj( Character :: toString )
                .toList();

characters.toString() = [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z]

Collect each String of three combined characters into List.

List < String > combinations = new ArrayList <>( characters.size() ^ 3 );

Then use the for-each syntax to loop that source list three times, nested, once for each position of your desired outputs.

for ( String firstCharacter : characters )
{
    for ( String secondCharacter : characters )
    {
        for ( String thirdCharacter : characters )
        {
            combinations.add( firstCharacter + secondCharacter + thirdCharacter );
        }
    }
}

Calling List#size gives you count you desire. Though mathematically we know that count should be ( 26 ^ 3 ) = 17,576.

System.out.println( combinations.size() + " combinations = " + combinations );

When run.

17576 combinations = [aaa, aab, aac, aad, aae, aaf, … zzw, zzx, zzy, zzz]

One-liner by using Stream#flatMap

We can even reduce that code down to a single-line, using the impressive code from the Comment by Holger.

The key part is a call to Stream#flatMap, used to generate many values from one value. To quote the Javadoc:

The flatMap() operation has the effect of applying a one-to-many transformation to the elements of the stream, and then flattening the resulting elements into a new stream.

By the way, concat is a static method. This seems a bit odd, given the other fluent-style methods on streams. If curious, see this Question.

So we start by transforming our stream of code points into a stream of Strings, each containing a single character. For each of our first characters, we create a bunch more code points transformed into String objects, for our second characters. We call flatMap again for each of those second characters, each one generating yet another stream of code points transformed into String objects for our third position. From there the first, second, and third characters are combined into a resulting string which we collect into our end result, an unmodifiable List< String >.

We get the same 17,576 combinations seen above.

List < String > combinations =
        IntStream
                .rangeClosed( "a".codePointAt( 0 ) , "z".codePointAt( 0 ) )
                .mapToObj( Character :: toString )
                .flatMap(
                        first ->
                                IntStream
                                        .rangeClosed( "a".codePointAt( 0 ) , "z".codePointAt( 0 ) )
                                        .mapToObj( Character :: toString )
                                        .flatMap( second ->
                                                IntStream
                                                        .rangeClosed( "a".codePointAt( 0 ) , "z".codePointAt( 0 ) )
                                                        .mapToObj( third -> first + second + Character.toString( third ) )
                                        )
                )
                .toList();

Multiple sets of inputs

The code above assumes we have a single range of characters to mix and match. Be aware that we could combine multiple ranges. Just call Stream.concat while passing a pair of streams.

In this example we mix and match lowercase ab along with uppercase AB. For a total of four characters being used in three position, we expect 4 ^ 3 = 64 combinations.

List < String > combinations =
        IntStream
                .concat(
                        IntStream.rangeClosed( "a".codePointAt( 0 ) , "b".codePointAt( 0 ) ) ,
                        IntStream.rangeClosed( "A".codePointAt( 0 ) , "B".codePointAt( 0 ) )
                )
                .mapToObj( Character :: toString )
                .flatMap(
                        first ->
                                IntStream
                                        .concat(
                                                IntStream.rangeClosed( "a".codePointAt( 0 ) , "b".codePointAt( 0 ) ) ,
                                                IntStream.rangeClosed( "A".codePointAt( 0 ) , "B".codePointAt( 0 ) )
                                        )
                                        .mapToObj( Character :: toString )
                                        .flatMap( second ->
                                                IntStream
                                                        .concat(
                                                                IntStream.rangeClosed( "a".codePointAt( 0 ) , "b".codePointAt( 0 ) ) ,
                                                                IntStream.rangeClosed( "A".codePointAt( 0 ) , "B".codePointAt( 0 ) )
                                                        )
                                                        .mapToObj( third -> first + second + Character.toString( third ) )
                                        )
                )
                .toList();

64 combinations.toString() = [aaa, aab, aaA, aaB, aba, abb, abA, abB, aAa, aAb, aAA, aAB, aBa, aBb, aBA, aBB, baa, bab, baA, baB, bba, bbb, bbA, bbB, bAa, bAb, bAA, bAB, bBa, bBb, bBA, bBB, Aaa, Aab, AaA, AaB, Aba, Abb, AbA, AbB, AAa, AAb, AAA, AAB, ABa, ABb, ABA, ABB, Baa, Bab, BaA, BaB, Bba, Bbb, BbA, BbB, BAa, BAb, BAA, BAB, BBa, BBb, BBA, BBB]

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • 2
    Instead of `IntStream .range( "a".codePointAt( 0 ) , "z".codePointAt( 0 ) + 1 )` you should use a straight-forward `IntStream.rangeClosed('a', 'z')`. And when you start using the Stream API, don’t stop using it midway. E.g. `List result = IntStream.rangeClosed('a', 'z').mapToObj(Character::toString) .flatMap(first -> IntStream.rangeClosed('a', 'z').mapToObj(Character::toString) .flatMap(second -> IntStream.rangeClosed('a', 'z') .mapToObj(third -> first + second + Character.toString(third)))) .toList();` – Holger Jun 03 '22 at 08:36
0
int n = 26; //no. of alphabet which is fix number
int p = 3;  //no. of alphabet we require in one combination like aaa,abc,bbb....
System.out.print(Math.pow(n,p));

for explanation of the formula read below description which will helpful

      **Easy mathematic formula**
    
    ***(fix number)^(no. of element in each combination)***
    
    It is just like no. of total combination of  when we toss a coin , when we throw two dice in probability.
    
    here each combination contains 3 alphabets so , let's take each alphabet from different pool(p1 , p2 , p3).
    
    p1  p2 p3
    __ ___ __
    a   a  a
    b   b  b
    c   c  c
    d   d  d
    .   .  .
    .   .  .
    .   .  .
    
    so here first take 1st alphabet 'a' from p1(pool1) and then take each alphabet from p2(pool2) so our result be like **aa,ab,ac,ad.....** . here we can see that when we take only 'a' then it creates 26 different combination. likewise each character of pool1(p1) has its own 26 different combination (like 'b' has 'ba','bb','bc'...  also c has'ca','cb','cc' and so on). 
    
    so total combination we can make from first two pool is 26*26.
    
    now let see how our new pool (new combinated pool) look likes...
    
    new pool**    **p3**
_____________     ________
    aa               a
    ab               b
    ac               c
    ad               d
    .                .
    .                .
    .                z
    .               ====
    zz              26
    =====
    26*26 
    
    now let's do the same process between **new pool** and **p3** , so our final result is (new pool characters)*(p3's characters)=[26**26]*26=17576
0

I once had a project where I wanted to generate a "binding code" and assign it to all boxes within a customer's order. Boxes where packed by pickers and then placed on conveyor belts which, ultimately, fed into a single spine before heading to the shipping dept where they were physically bound together for each carrier (bound by order# & carrier, since part of the order might be overnight and the remainder via 5-day). The conveyor feed often resulted in an order's boxes being separated, before reaching the shipping dept. To ease the shipping clerk's task of gathering the related boxes (by order/carrier), I wanted to include a large 3-character alphabetic value in the top-left of the otherwise complex shipping label. This value would visually represent the order/carrier combination, making it painless for the clerk to visually locate (quickly and accurately) all related boxes without having to examine each box's complex label to discern their relation.

EG: AAA, AAB, AAC, BAA, ZZZ

Hence, the application generating the shipping label needed to create this value per order/carrier. Each unique combination incremented a control counter .. and this counter was then used to generate the character value. The control number was recycled, after reaching the maximum, and the gap was sufficient to ensure no overlap during the business day.

Here's the logic I employed. Perhaps, you will find it of good value, for this question or anyone else seeking to do similarly. Of course, if more than 3 alphabetic chars are needed, the logic can be easily adapted.

Goal:

Convert control number to 3 alphabetic chars (i.e. AAA thru ZZZ)
That's 26^3 = 17576 combinations (note: ensure this is enough chars to provide sufficient gap before recycle)
Numeric Range: 0 thru 17575 (zero-based)

Steps:

1. Apply Modulo 26 to Number and convert Remainder to 3rd-pos character (__#)
2. Apply Modulo 26 to Quotient from prior step and convert Remainder to 2nd-pos character (_#_)
3. Apply Modulo 26 to Quotient from prior step and convert Remainder to 1st-pos character (#__)

Conversion Table:

    ABCDEFGHIJKLMNOPQRSTUVWXYZ
    00000000001111111111222222
    01234567890123456789012345

Run-time Examples:

17575

    17575 mod 26 = 675 R25 (25 = "Z") 3rd pos
    675   mod 26 =  25 R25 (25 = "Z") 2nd pos
    25    mod 26 =   0 R25 (25 = "Z") 1st pos
    Answer: ZZZ

0

    0 mod 26 = 0 R0 (0 = "A") 3rd pos (__#)
    0 mod 26 = 0 R0 (0 = "A") 2nd pos (_#_)
    0 mod 26 = 0 R0 (0 = "A") 1st pos (#__)
    Answer: AAA

1

    1 mod 26 = 0 R1 (1 = "B") 3rd pos
    0 mod 26 = 0 R0 (0 = "A") 2nd pos
    0 mod 26 = 0 R0 (0 = "A") 1st pos
    Answer: AAB

676

    676 mod 26 = 26 R0 (0 = "A") 3rd pos (__#)
    26  mod 26 =  1 R0 (0 = "A") 2nd pos (_#_)
    1   mod 26 =  0 R1 (1 = "B") 1st pos (#__)
    Answer: BAA

971

    971 mod 26 = 37 R9  (9  = "J") 3rd pos
    37  mod 26 =  1 R11 (11 = "L") 2nd pos
    1   mod 26 =  0 R1  (1  = "B") 1st pos
    Answer: BLJ

As an aside, I also prohibited naughty combinations (eg: TIT), leveraging a preset list to skip undesirable acronyms.

Modulo Calculator: https://www.calculatorsoup.com/calculators/math/modulo-calculator.php

Regards,
Paulie D

Paulie D
  • 11
  • 3