create your own number system using python - 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

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

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))

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))).

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)

Related

Is there an easy way to get the number of repeating character in a word?

I'm trying to get how many any character repeats in a word. The repetitions must be sequential.
For example, the method with input "loooooveee" should return 6 (4 times 'o', 2 times 'e').
I'm trying to implement string level functions and I can do it this way but, is there an easy way to do this? Regex, or some other sort of things?
Original question: order of repetition does not matter
You can subtract the number of unique letters by the number of total letters. set applied to a string will return a unique collection of letters.
x = "loooooveee"
res = len(x) - len(set(x)) # 6
Or you can use collections.Counter, subtract 1 from each value, then sum:
from collections import Counter
c = Counter("loooooveee")
res = sum(i-1 for i in c.values()) # 6
New question: repetitions must be sequential
You can use itertools.groupby to group sequential identical characters:
from itertools import groupby
g = groupby("aooooaooaoo")
res = sum(sum(1 for _ in j) - 1 for i, j in g) # 5
To avoid the nested sum calls, you can use itertools.islice:
from itertools import groupby, islice
g = groupby("aooooaooaoo")
res = sum(1 for _, j in g for _ in islice(j, 1, None)) # 5
You could use a regular expression if you want:
import re
rx = re.compile(r'(\w)\1+')
repeating = sum(x[1] - x[0] - 1
for m in rx.finditer("loooooveee")
for x in [m.span()])
print(repeating)
This correctly yields 6 and makes use of the .span() function.
The expression is
(\w)\1+
which captures a word character (one of a-zA-Z0-9_) and tries to repeat it as often as possible.
See a demo on regex101.com for the repeating pattern.
If you want to match any character (that is, not only word characters), change your expression to:
(.)\1+
See another demo on regex101.com.
try this:
word=input('something:')
sum = 0
chars=set(list(word)) #get the set of unique characters
for item in chars: #iterate over the set and output the count for each item
if word.count(char)>1:
sum+=word.count(char)
print('{}|{}'.format(item,str(word.count(char)))
print('Total:'+str(sum))
EDIT:
added total count of repetitions
Since it doesn't matter where the repetition is occurring or which characters are being repeated, you can make use of the set data structure provided in Python. It will discard the duplicate occurrences of any character or an object.
Therefore, the solution would look something like this:
def measure_normalized_emphasis(text):
return len(text) - len(set(text))
This will give you the exact result.
Also, make sure to look out for some edge cases, which you should as it is a good practice.
I think your code is comparing the wrong things
You start by finding the last character:
char = text[-1]
Then you compare this to itself:
for i in range(1, len(text)):
if text[-i] == char: #<-- surely this is test[-1] to begin with?
Why not just run through the characters:
def measure_normalized_emphasis(text):
char = text[0]
emphasis_size = 0
for i in range(1, len(text)):
if text[i] == char:
emphasis_size += 1
else:
char = text[i]
return emphasis_size
This seems to work.

How to loop to generate string in sequence?

I am trying to create a loop where I can generate string using loop. What I am trying to achieve is that I want to create a small collection of strings starting from 1 character to up to 5 characters.
So, starting from sting 1, I want to go to 55555 but this is number so it seems easy if I just add them, but when it comes to alpha numeric, it gets tricky.
Here is explanation,
I have collection of alpha-numeric chars as string s = "123ABC" and what I want to do is that I want to create all possible 1 character string out of it, so I will have 1,2,3,A,B,C and after that I want to add one more digit in length of string so I can get 11, 12, 13 and so on until I get all possible combination out of it up to CA, CB, CC and I want to get it up to CCCCCC. I am confused in loop because I can get it to generate a temp sting but looping inside to rotate characters is tricky,
this is what I have done so far,
i = 0
strr = "123ABC"
while i < len(strr):
t = strr[0] * (i+1)
for q in range(0, len(t)):
# Here I need help to rotate more
pass
i += 1
Can anyone explain me or point me to resource where I can find solution for it?
You may want to use itertools.permutations function:
import itertools
chars = '123ABC'
for i in xrange(1, len(chars)+1):
print list(itertools.permutations(chars, i))
EDIT:
To get a list of strings, try this:
import itertools
chars = '123ABC'
strings = []
for i in xrange(1, len(chars)+1):
strings.extend(''.join(x) for x in itertools.permutations(chars, i))
This is a nested loop. Different depths of recursion produce all possible combinations.
strr = "123ABC"
def prod(items, level):
if level == 0:
yield []
else:
for first in items:
for rest in prod(items, level-1):
yield [first] + rest
for ln in range(1, len(strr)+1):
print("length:", ln)
for s in prod(strr, ln):
print(''.join(s))
It is also called cartesian product and there is a corresponding function in itertools.

How can i start itertools combinations from specific letter/digit?

I have a code like this:
start = 1
end = 2
for length in range(start, end+1):
for c in itertools.combinations_with_replacement(string.ascii_letters + string.digits, length):
this will print every uppercase/lowercase letter from A to Z and after all letters are finished, It will start printing all digits from 0 to 9. so it looks like this: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
After first cycle is done, it goes on second one and does the same thing.
like this:
First cycle starting: a
Second cycle starting: aa
and etc.
what i want it to do:
I want to start combinations from specific letter or digit.
Like this:
Combination 1:
First cycle starting: b
Second cycle starting: ba
If it is not possible, then like this:
Combination 2:
First cycle starting: b
Second cycle starting: bb
I think you're asking for all possible permuations after a certain index in which case you can do:
import string
import itertools
chars = string.ascii_letters + string.digits
def alpha_perms(index):
return list(itertools.permutations(chars[index:]))
print(alpha_perms(0)) #0th index to go along with the below statement
Although... this will most likely (absolutely) freeze your machine. There are 62 characters in chars thats 62! (62 factorial) which is approximately equal to 3.1469973e+85 or ~π*10^85th power possible combinations assuming you passed in the 0th index. Even a reasonable index is going to take a long time.
Alternatively, since using return list(...) will cause problems for high combination possibilities. You could yield the value
import string
import itertools
chars = string.ascii_letters + string.digits
def alpha_perms(index):
for perm in itertools.permutations(chars[index:]):
yield perm

Python - build new string of specific length with n replacements from specific alphabet

I have been working on a fast, efficient way to solve the following problem, but as of yet, I have only been able to solve it using a rather slow, nest-loop solution. Anyways, here is the description:
So I have a string of length L, lets say 'BBBX'. I want to find all possible strings of length L, starting from 'BBBX', that differ at, at most, 2 positions and, at least, 0 positions. On top of that, when building the new strings, new characters must be selected from a specific alphabet.
I guess the size of the alphabet doesn't matter, so lets say in this case the alphabet is ['B', 'G', 'C', 'X'].
So, some sample output would be, 'BGBG', 'BGBC', 'BBGX', etc. For this example with a string of length 4 with up to 2 substitutions, my algorithm finds 67 possible new strings.
I have been trying to use itertools to solve this problem, but I am having a bit of difficulty finding a solution. I try to use itertools.combinations(range(4), 2) to find all the possible positions. I am then thinking of using product() from itertools to build all of the possibilities, but I am not sure if there is a way I could connect it somehow to the indices from the output of combinations().
Here's my solution.
The first for loop tells us how many replacements we will perform. (0, 1 or 2 - we go through each)
The second loop tells us which letters we will change (by their indexes).
The third loop goes through all of the possible letter changes for those indexes. There's some logic to make sure we actually change the letter (changing "C" to "C" doesn't count).
import itertools
def generate_replacements(lo, hi, alphabet, text):
for count in range(lo, hi + 1):
for indexes in itertools.combinations(range(len(text)), count):
for letters in itertools.product(alphabet, repeat=count):
new_text = list(text)
actual_count = 0
for index, letter in zip(indexes, letters):
if new_text[index] == letter:
continue
new_text[index] = letter
actual_count += 1
if actual_count == count:
yield ''.join(new_text)
for text in generate_replacements(0, 2, 'BGCX', 'BBBX'):
print text
Here's its output:
BBBX GBBX CBBX XBBX BGBX BCBX BXBX BBGX BBCX BBXX BBBB BBBG BBBC GGBX
GCBX GXBX CGBX CCBX CXBX XGBX XCBX XXBX GBGX GBCX GBXX CBGX CBCX CBXX
XBGX XBCX XBXX GBBB GBBG GBBC CBBB CBBG CBBC XBBB XBBG XBBC BGGX BGCX
BGXX BCGX BCCX BCXX BXGX BXCX BXXX BGBB BGBG BGBC BCBB BCBG BCBC BXBB
BXBG BXBC BBGB BBGG BBGC BBCB BBCG BBCC BBXB BBXG BBXC
Not tested much, but it does find 67 for the example you gave. The easy way to connect the indices to the products is via zip():
def sub(s, alphabet, minsubs, maxsubs):
from itertools import combinations, product
origs = list(s)
alphabet = set(alphabet)
for nsubs in range(minsubs, maxsubs + 1):
for ix in combinations(range(len(s)), nsubs):
prods = [alphabet - set(origs[i]) for i in ix]
s = origs[:]
for newchars in product(*prods):
for i, char in zip(ix, newchars):
s[i] = char
yield "".join(s)
count = 0
for s in sub('BBBX', 'BGCX', 0, 2):
count += 1
print s
print count
Note: the major difference from FogleBird's is that I posted first - LOL ;-) The algorithms are very similar. Mine constructs the inputs to product() so that no substitution of a letter for itself is ever attempted; FogleBird's allows "identity" substitutions, but counts how many valid substitutions are made and then throws the result away if any identity substitutions occurred. On longer words and a larger number of substitutions, that can be much slower (potentially the difference between len(alphabet)**nsubs and (len(alphabet)-1)**nsubs times around the ... in product(): loop).

Replacing chars in a string in every way

I'm looking for help on a function that takes a string, and replaces every character in that string in every way. I'm not quite sure how to word my question so that it makes sense so I'll show you what it's supposed to do.
stars('1')
returns ['*']
stars('12')
returns ['*1', '1*', '**']
stars('123')
returns ['*23', '1*3', '12*', '**3', '*2*', '**1', '***']
stars('1234')
returns ['*234', '1*34', '12*4', '123*', '**34', '*2*4', '*23*', '1**4', '1*3*',
'12**', '***4', '**3*', '*2**', '1***', '****']
Did that all out by hand, but even if I made a mistake, you should get the idea of what I'm looking for now. The final case (all *'s) isn't required but I put it in there to make sure the problem was understood.
Here is what I've come up with so far but it doesn't quite work.
def stars(n):
lst = []
length = len(n)
for j in xrange(0, length):
p = list(n)
for k in xrange(j, length):
p[k] = '*'
lst += [''.join(p)]
return lst
Output:
'1' returns ['*']
'12' returns ['*2', '**', '1*']
'123' returns ['*23', '**3', '***', '1*3', '1**', '12*']
'1234' returns ['*234', '**34', '***4', '****', '1*34', '1**4', '1***', '12*4', '12**', '123*']
Any help would be greatly appreciated. Would like this answered in Python if possible, but if you don't know Python, then pseudocode or another language would be acceptable. If it's written clearly, I'm sure I could convert it into Python on my own.
I think the canonical approach in Python would be to use the itertools module:
>>> from itertools import product, cycle
>>> s = 'abcde'
>>> [''.join(chars) for chars in product(*zip(s, cycle('*')))]
['abcde', 'abcd*', 'abc*e', 'abc**', 'ab*de', 'ab*d*', 'ab**e', 'ab***',
'a*cde', 'a*cd*', 'a*c*e', 'a*c**', 'a**de', 'a**d*', 'a***e', 'a****',
'*bcde', '*bcd*', '*bc*e', '*bc**', '*b*de', '*b*d*', '*b**e', '*b***',
'**cde', '**cd*', '**c*e', '**c**', '***de', '***d*', '****e', '*****']
and then you could just toss the first one without any stars, but that might seem a little magical.
ISTM you have two other approaches if you don't want to use the built-in Cartesian product function: you can use recursion, or you can take advantage of the fact that you want to turn each star on and off, a binary switch. That means with n letters you'll have 2^n (-1, if you remove the no-star case) possibilities to return, and whether or not to put a star somewhere corresponds to whether or not the corresponding bit in the number is set (e.g. for 'abc' you'd loop from 1 to 7 inclusive, 1 = 001 so you'd put a star in the last place, 7 = 111 so you'd put a star everywhere, etc.)
This last one is pretty simple to implement, so I'll leave that for you. :^)
You can look at this as a problem of finding and iterating over all subsequences of characters in your original string. (For every subsequence, replace the characters in it by '*', and leave the rest alone).
For a given subsequence, each character is either in it or not, so for an N-character string, there are 2^N subsequences. Probably the easiest way to iterate over them is to iterate over the integers from 0 to (2^N)-1, and use their binary representations as the indications of whether the character should be replaced or not
For N=3, it looks like this:
0 000 abc
1 001 ab*
2 010 a*c
3 011 a**
4 100 *bc
5 101 *b*
6 110 **c
7 111 ***
In Python, you could do it like this:
def stars(input):
l = len(input)
for i in xrange(2**l):
yield ''.join([('*' if i&(2**(l-pos-1)) else ch) for pos, ch in enumerate(input)])
Try it out:
>>> print list(stars('abc'))
['abc', 'ab*', 'a*c', 'a**', '*bc', '*b*', '**c', '***']
Here's a way using combinations :
from itertools import combinations
def stars(str):
N,L = len(str), []
for k in range(0,N+1):
for com in combinations(range(N),k):
S = list(str)
for x in com: S[x] = '*'
L.append(''.join(S))
return L
Try it out:
>>> stars('abc')
['abc', '*bc', 'a*c', 'ab*', '**c', '*b*', 'a**', '***']
>>> stars('1234')
['1234', '*234', '1*34', '12*4', '123*', '**34', '*2*4', '*23*', '1**4', '1*3*', '12**', '***4', '**3*', '*2**', '1***', '****']
Or specific to Python see this function: http://docs.python.org/2/library/itertools.html#itertools.combinations

Categories