Mathew
Mathew

Reputation: 129

create your own number system using python

I am making a small program that guesses a password.

I am making this program just for the purpose of learning, I want to improve my python skills by making a program that have a real meaning.

for example:

using_characts = "abcdefghijklmnopqrstuvwxyz" # I have other characters in my alphabetic system

What I want to do is something like this:

for char in myCharacters:
    print(char)
    for char_1 in myCharacters:
        print(char + char_1)
        for char_2 in myCharacters:
            print(char + char_1 + char_2)
            ...etc

which makes this method non dynamic, and hard in the same time. the output should be something like this:

a

b

c

d

e

f

..etc

aa

ab

ac

..etc

ba

bb

bc

..etc

Upvotes: 1

Views: 688

Answers (4)

izhang05
izhang05

Reputation: 764

The following code will give you all combinations with lengths between 1 and max_length - 1:

import itertools

combs = []

for i in range(1, max_length):
    c = [list(x) for x in itertools.combinations(using_characts, i)]
    combs.extend(c)

Upvotes: 0

asthasr
asthasr

Reputation: 9397

So, the other answers have given you code that will probably work, but I wanted to explain a general approach. This algorithm uses a stack to keep track of the next things that need to be generated, and continues generating until it reaches the maximum length that you've specified.

from collections import deque
from typing import Deque, Iterator, Optional


def generate_next_strings(chars: str, base: str = "") -> Iterator[str]:
    # This function appends each letter of a given alphabet to the given base.
    # At its first run, it will generate all the single-length letters of the
    # alphabet, since the default base is the empty string.
    for c in chars:
        yield f"{base}{c}"


def generate_all_strings(chars: str, maxlen: Optional[int] = None) -> Iterator[str]:
    # We "seed" the stack with a generator. This generator will produce all the
    # single-length letters of the alphabet, as noted above.
    stack: Deque[Iterator[str]] = deque([generate_next_strings(chars)])

    # While there are still items (generators) in the stack...
    while stack:
        # ...pop the next one off for processing.
        next_strings: Iterator[str] = stack.popleft()

        # Take each item from the generator that we popped off,
        for string in next_strings:
            # and send it back to the caller. This is a single "result."
            yield string

            # If we're still generating strings -- that is, we haven't reached
            # our maximum length -- we add more generators to the stack for the
            # next length of strings.
            if maxlen is None or len(string) < maxlen:
                stack.append(generate_next_strings(chars, string))

You can try it using print("\n".join(generate_all_strings("abc", maxlen=5))).

Upvotes: 1

JimmyCarlos
JimmyCarlos

Reputation: 1952

Here you go, this will work. Let me know if you want me to explain any part.

import itertools

using_characts = "abc"

for str_length in range(1,len(using_characts)+1):
    for q in itertools.product(using_characts,repeat=str_length):
        print("".join(q))

Upvotes: 1

sahinakkaya
sahinakkaya

Reputation: 6056

You can use itertools.product but you should really limit yourself with a small number. Generating cartesian product for higher numbers can take really long time:

from itertools import chain, product
chars = "abcdefghijklmnopqrstuvwxyz"
limit = 2
for perm in chain.from_iterable(product(chars, repeat=i) for i in range(1, limit+1)):
    print("".join(perm))
a
b
c
.
.
.
aa
ab
ac
.
.
.
zy
zz

Upvotes: 1

Related Questions