1

I'm stuck at this subject about 3 days, I can't think a proper algorithm. So could you please help me guys.

I want to generate wordlist with given charset, minimum & maximum length

Given charset:abcdef min:2 max:5

Result:

aa
ab
ac
...
ffffd
ffffe
fffff

Like linux command line crunch.

But there's something, I need to make this in a for loop doesn't matter how many loops but matters without calling any user-made functions*.

Like:

for (...) {

   // Password is ready!
   pass = ...;

}

And NOT like:


pass = get_pass(...);

Thank you.

ALWIEZ
  • 59
  • 1
  • 7
  • 3
    I agree with you, it is not an easy task, maybe people think that you should show a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) along with your question. That would you increase your chances to get help. However, I will try to help you later on if no one else posts an answer and (of course) the post doesn't get closed. – Marco Tizzano May 20 '21 at 09:17
  • Also worth a look : [string-letter-combinations-using-n-choose-k-using-java](https://stackoverflow.com/questions/33965227/string-letter-combinations-using-n-choose-k-using-java) – Eritrean May 20 '21 at 09:47

3 Answers3

1

One way could be to use a libraray which creates strings from a given regex like Generex. Using Generex your task is as simple as:

import com.mifmif.common.regex.Generex;

public class Example {

    public static void main(String[] args) {
        Generex gen = new Generex("[abcdef]{2,5}");
        gen.getAllMatchedStrings().forEach(System.out::println);
    }
} 

output:

aa
aaa
aaaa
aaaaa
aaaab
aaaac
aaaad
aaaae
aaaaf
...
...
ffffa
ffffb
ffffc
ffffd
ffffe
fffff

See this post for other libs like generex using-regex-to-generate-strings-rather-than-match-them

Eritrean
  • 9,903
  • 1
  • 15
  • 20
  • Thank you, so clever way to do this, unfortunately external libraries is not giving me an algorithm, also it's not sequentially enough. But if no one comes with another solution I'm going to flag this as an answer and implant this to project. Thank you so much x999. – ALWIEZ May 20 '21 at 09:52
1

I'm pretty sure that it's not the best possible solution, but it works.

public static void main(String[] args) {
    List<Character> charset = new ArrayList<>();
    charset.add('a');
    charset.add('b');
    charset.add('c');
    charset.add('d');
    charset.add('e');
    int min = 2;
    int max = 5;

    List<Integer> word = new ArrayList<>();
    for (int len = min; len <= max; len++) {
        word.clear();
        for (int i = 0; i < len; i++) {
            word.add(0);
        }
        while (word.get(0) < charset.size()) {
            System.out.println(word.stream().map(e -> charset.get(e).toString()).collect(Collectors.joining()));
            word.set(len - 1, word.get(len - 1) + 1);
            for (int i = len - 1; i > 0; i--) {
                if (word.get(i).equals(charset.size())) {
                    word.set(i-1, word.get(i-1) + 1);
                    word.set(i, 0);
                } else {
                    break;
                }
            }
        }
    }
}
Ruslan
  • 36
  • 6
  • Do you know a fix for 17. line (Call requires API level 24 (current min is 21)) is this error raising cause of "e -> ...", or it's about collector, it freezes the UI min 3+ but I think if I can fix this API problem, I can handle the other, so much thank you! – ALWIEZ May 20 '21 at 18:55
  • 1
    I'm not really good in Android API. Anyway, If you thing that there is something wrong with streams? you can change that line to something like `StringBuilder resultString = new StringBuilder(); for (int index: word) {resultString.append(charset.get(index));} System.out.println(resultString.toString());` – Ruslan May 21 '21 at 08:48
1

Another approach is to interpret your charset as digits of a numbersystem and your desired output as all n digit numbers. For example, in decimal system we have the digits 0 to 9 and all two-digit numbers (with leading zero) would be the numbers

00 - 99

three-digit

000 - 999 

and so on. In octal system, however, your numbers would go from

00 - 77 or from

000 - 777

and in binary

00 - 11 or

000 - 111

If we now replace in your charset the letters with digits, i.e. a with 0, b with 1, c with 2 ...

aaa in your output is the same as 000 and fff the same as 555. That means the task is to create all two-digit, three-digit, ...., 5-digit numbers in the base six number system (charset length) and convert the digits back to the letters from the given charset. A starting point for such an algorithm could be something like:

public static void main(String[] args) {
    String str = "abcdef";

    //create a map which looks like {0=a, 1=b, 2=c, 3=d, 4=e, 5=f}
    Map<Character,Character> map = new HashMap<>();
    for(int i = 0; i <str.length(); i ++){
        map.put((char)(i+'0'), str.charAt(i));
    } 

    //convert numbers to string using //Integer.toString(int i, int radix)
    //use String#format & String#replace to have a string representation with leading zeros
    for(int n = 2; n <= 5; n++){
        int maxValue = (int)Math.pow(str.length(), n);
        for(int i = 0; i < maxValue; i++){
            String temp = String.format("%"+n+"s", Integer.toString(i, str.length())).replace(' ', '0');
            for(char c: map.keySet()){
                temp = temp.replace(c, map.get(c));
            }                
            System.out.println(temp);
        }
    }
}
Eritrean
  • 9,903
  • 1
  • 15
  • 20
  • This code is may be my solution, just it freezes the UI at min 3+, and suddenly stops at 'p', I mean 'pp', 'ppp'... – ALWIEZ May 20 '21 at 18:59