Why does Python 3 for loop output and behave differently? - python

This is a password generator, I couldn't really determine where the problem is, but from the output, I could say it's around turnFromAlphabet()
The function turnFromAlphabet() converts an alphabetical character to its integer value.
The random module, I think doesn't do anything here as it just decides whether to convert a character in a string to uppercase or lowercase. And if a string is in either, when sent or passed to turnFromAlphabet() it is converted to lowercase first to avoid errors but there are still errors.
CODE:
import random
import re
#variables
username = "oogisjab" #i defined it already for question purposes
index = 0
upperOrLower = []
finalRes = []
index2a = 0
#make decisions
for x in range(len(username)):
decision = random.randint(0,1)
if(decision is 0):
upperOrLower.append(True)
else:
upperOrLower.append(False)
#Apply decisions
for i in range(len(username)):
if(upperOrLower[index]):
finalRes.append(username[index].lower())
else:
finalRes.append(username[index].upper())
index+=1
s = ""
#lowkey final
s = s.join(finalRes)
#reset index to 0
index = 0
def enc(that):
if(that is "a"):
return "#"
elif(that is "A"):
return "4"
elif(that is "O"):
return "0" #zero
elif(that is " "):
# reduce oof hackedt
decision2 = random.randint(0,1)
if(decision2 is 0):
return "!"
else:
return "_"
elif(that is "E"):
return "3"
else:
return that
secondVal = []
for y in range(len(s)):
secondVal.append(enc(s[index]))
index += 1
def turnFromAlphabet(that, index2a):
alp = "abcdefghijklmnopqrstuvwxyz"
alp2 = list(alp)
for x in alp2:
if(str(that.lower()) == str(x)):
return index2a+1
break
else:
index2a += 1
else:
return "Error: Input is not in the alphabet"
#real final
finalOutput = "".join(secondVal)
#calculate some numbers and chars from a substring
amount = len(finalOutput) - round(len(finalOutput)/3)
getSubstr = finalOutput[-(amount):]
index = 0
allFactors = {
};
#loop from substring
for x in range(len(getSubstr)):
hrhe = re.sub(r'\d', 'a', ''.join(e for e in getSubstr[index] if e.isalnum())).replace(" ", "a").lower()
print(hrhe)
#print(str(turnFromAlphabet("a", 0)) + "demo")
alpInt = turnFromAlphabet(hrhe, 0)
print(alpInt)
#get factors
oneDimensionFactors = []
for p in range(2,alpInt):
# if mod 0
if(alpInt % p) is 0:
oneDimensionFactors.append(p)
else:
oneDimensionFactors.append(1)
indexP = 0
for z in oneDimensionFactors:
allFactors.setdefault("index{0}".format(index), {})["keyNumber"+str(p)] = z
index+=1
print(allFactors)

I think that you are getting the message "Error: input is not in the alphabet" because your enc() change some of your characters. But the characters they becomes (for example '#', '4' or '!') are not in your alp variable defined in turnFromAlphabet(). I don't know how you want to fix that. It's up to you.
But I have to say to your code is difficult to understand which may explain why it can be difficult for you to debug or why others may be reluctant to help you. I tried to make sense of your code by removing code that don't have any impact. But even in the end I'm not sure I understood what you tried to do. Here's what I understood of your code:
import random
import re
#username = "oogi esjabjbb"
username = "oogisjab" #i defined it already for question purposes
def transform_case(character):
character_cases = ('upper', 'lower')
character_to_return = character.upper() if random.choice(character_cases) == 'upper' else character.lower()
return character_to_return
username_character_cases_modified = "".join(transform_case(current_character) for current_character in username)
def encode(character_to_encode):
translation_table = {
'a' : '#',
'A' : '4',
'O' : '0',
'E' : '3',
}
character_translated = translation_table.get(character_to_encode, None)
if character_translated is None:
character_translated = character_to_encode
if character_translated == ' ':
character_translated = '!' if random.choice((True, False)) else '_'
return character_translated
final_output = "".join(encode(current_character) for current_character in username_character_cases_modified)
amount = round(len(final_output) / 3)
part_of_final_output = final_output[amount:]
all_factors = {}
for (index, current_character) in enumerate(part_of_final_output):
hrhe = current_character
if not hrhe.isalnum():
continue
hrhe = re.sub(r'\d', 'a', hrhe)
hrhe = hrhe.lower()
print(hrhe)
def find_in_alphabet(character, offset):
alphabet = "abcdefghijklmnopqrstuvwxyz"
place_found = alphabet.find(character)
if place_found == -1 or not character:
raise ValueError("Input is not in the alphabet")
else:
place_to_return = place_found + offset + 1
return place_to_return
place_in_alphabet = find_in_alphabet(hrhe, 0)
print(place_in_alphabet)
def provide_factors(factors_of):
for x in range(1, int(place_in_alphabet ** 0.5) + 1):
(quotient, remainder) = divmod(factors_of, x)
if remainder == 0:
for current_quotient in (quotient, x):
yield current_quotient
unique_factors = set(provide_factors(place_in_alphabet))
factors = sorted(unique_factors)
all_factors.setdefault(f'index{index}', dict())[f'keyNumber{place_in_alphabet}'] = factors
print(all_factors)
Is near what your wanted to do?

Related

Counting occurrences of multiple characters in a string, with python

I'm trying to create a function that -given a string- will return the count of non-allowed characters ('error_char'), like so: 'total count of not-allowed / total length of string'.
So far I've tried:
def allowed_characters(s):
s = s.lower()
correct_char = 'abcdef'
error_char = 'ghijklmnopqrstuvwxyz'
counter = 0
for i in s:
if i in correct_char:
no_error = '0'+'/'+ str(len(s))
return no_error
elif i in error_char:
counter += 1
result = str(sum(counter)) + '/' + str(len(s))
return result
but all I get is '0/56' where I'm expecting '22/56' since m,x,y,z are 'not allowed' and m repeats 19 times
allowed_characters('aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbmmmmmmmmmmmmmmmmmmmxyz')
'0/56'
Then I've tried:
def allowed_characters(s):
s = s.lower()
correct_char = 'abcdef'
error_char = 'ghijklmnopqrstuvwxyz'
counter = 0
for i in s:
if i in correct_char:
no_error = '0'+'/'+ str(len(s))
return no_error
elif i in error_char:
import regex as re
rgx_pattern = re.compile([error_char])
count_e = rgx_pattern.findall(error_char, s)
p_error = sum([count_e.count(i) for i in error_char])
result = str(p_error) + '/' + str(len(s))
But I get the same result...
I've also tried these other ways, but keep getting the same:
def allowed_characters1(s):
s = s.lower()
correct_char = 'abcdef'
for i in s:
if i not in correct_char:
counter = sum([s.count(i) for i in s])
p_error = str(counter) + '/' + str(len(s))
return p_error
elif i in correct_char:
no_error = '0'+'/'+ str(len(s))
return no_error
and...
def allowed_characters2(s):
s = s.lower()
correct_char = 'abcdef'
for i in s:
if i not in correct_char:
counter = sum(s.count(i))
p_error = str(counter) + '/' + str(len(s))
return p_error
elif i in correct_char:
no_error = '0'+'/'+ str(len(s))
return no_error
I've even tried changing the logic and iterating over 'correct/error_char' instead, but nothing seems to work... I keep getting the same result over and over. It looks as though the loop stops right after first character or doesn't run the 'elif' part?
Whenever it comes to do quicker counting - it's always good to think about Counter You can try to simplify your code like this:
Notes - please don't change your Problem Description during the middle of people's answering posts. That make it very hard to keep in-sync.
There is still room to improve it though.
from collections import Counter
def allowed_char(s):
s = s.lower()
correct_char = 'abcdef'
error_char = 'ghijklmnopqrstuvwxyz'
ok_counts = Counter(s)
print(f' allowed: {ok_counts} ')
correct_count = sum(count for c, count in ok_counts.items() if c in correct_char)
error_count = sum(count for c, count in ok_counts.items() if c in error_char)
#return sum(not_ok.values()) / total
return correct_count, error_count # print both
s =('aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbmmmmmmmmmmmmmmmmmmmxyz')
print(allowed_char(s)) # (34, 22)
print(allowed_char('abdmmmmxyz')) # (3, 7)
Alternatively, you really want to use for-loop and learn to process the string of characters, you could try this:
def loop_count(s):
s = s.lower()
correct_count = error_count = 0
for c in s:
if c in correct_char:
correct_count += 1
else:
error_count += 1
return correct_count, error_count
I would use a regex replacement trick here using len():
def allowed_characters(s):
return len(s) - len(re.sub(r'[^ghijklmnopqrstuvwxyz]+', '', s))
The above returns the length of the input string minus the length of the input with all allowed characters removed (alternatively minus the length of the string with only non allowed characters).

How to replace an old value in a string with a new one?

So the problem states that if the given word in a sentence begins and ends with the same character I remove that character and keep on doing that until they are not the same anymore or their length is less than 3.
Example: aabaa -> aba -> b
And that is not the problem, so now I should replace the word 'aabaa' with 'b' in original string.
The only problem i have is when the sentence is given without spaces. For example:
Trust,is,all. -> rus,is,all.
Also to note characters such as (. , ! ? ; :) are to be ignored but have to be there in the final output.
So far I've wrote this but it doesn't satisfy the example above:
s1 = str(input())
sentence = s1.split()
news = []
ignorabelCharacters = ['.',',','!','?',';',':']
helpList = []
for i in range(len(s1)):
if s1[i] in ignorabelCharacters:
helpList.append([s1[i],i])
for i in sentence:
i = str(i)
j = 0
while j < len(i):
if i[j] in ignorabelCharacters:
i = i.replace(i[j],' ').strip()
j+=1
else:j+=1
news.append(i)
s2 =' '.join(news)
newSentence = s2.split()
def checkAgain(newSentence):
newNewSentance = []
count = []
x=0
for i in newSentence:
j = len(i)
while j > 2:
if i[0].lower() == i[-1] or i[0].upper() == i[-1]:
i = i[1:-1]
j-=2
x+=2
else:
break
count.append(x)
newNewSentance.append(i)
x=0
return [newNewSentance,count]
newNewSentence = checkAgain(newSentence)[0]
count = checkAgain(newSentence)[1]
def finalProcessing(newNewSentence,sentence,newSentence):
finalSentence = []
for i in range(len(sentence)):
if len(newNewSentence[i]) == len(sentence[i]):
finalSentence.append(newNewSentence[i])
else:
x = len(sentence[i]) - len(newSentence[i])
if x ==0:
finalSentence.append(newNewSentence[i])
else:
value = newNewSentence[i] + sentence[i][-x:]
finalSentence.append(value)
return finalSentence
finalSentence = finalProcessing(newNewSentence,sentence,newSentence)
def finalPrint(finalSentece):
for i in range(len(finalSentece)):
if i == len(finalSentece) -1:
print(finalSentece[i],end='')
else:
print(finalSentece[i],end= ' ')
finalPrint(finalSentence)
This approach is different from yours but here is how I would do it.
def condenseWord(w):
ln = len(w)
while ln >= 3:
if w[0].lower() == w[-1].lower():
w = w[1:-1]
ln = len(w)
else:
break
return w
def collapseString(s):
sep_chars = {' ', ',', '.', ';', ':', '!', '"', "'"}
out = r''
wdstrt = 0
lstltr = 0
for i in range(len(s)):
if s[i] in sep_chars:
ck = condenseWord(s[wdstrt:i])
out += ck
out += s[i]
wdstrt = i+1
lstltr = i+1
else:
lstltr = i
out += s[wdstrt:lstltr]
return out
Then
collapseString('aabaa') -> 'b', and
collapseString('Trust,is,all.' ) -> 'rus,is,all.'

Type error: function() missing 1 required positional argument: 's'

Im new to python and im trying to write algorithm to find the longest sub string without repeating characters. I keep getting this Error: " lengthOfLongestSubstring() missing 1 required positional argument: 's' ", when i obviously call the function with the argument. why is it heppening? Thanks for any help.
class Solution:
def lengthOfLongestSubstring(self, s):
arr = [char1 for char1 in s]
help_arr = [i*0 for i in range(26)]
sub_strings = []
sub = ""
for char in s:
index = ord(char) - ord('a')
if help_arr[index] == 0:
help_arr[index] = int(1)
sub += char
else:
sub_strings.append(sub)
sub = ""
sub += char
help_arr = [i * 0 for i in range(26)]
help_arr[index] = int(1)
max(sub_strings)
def max(arr):
max = 0
index = -1
for i in range(len(arr)):
if len(arr[i]) > max:
max = len(arr[i])
index= i
return print("The answer is '{}', with the length of {}.".format(arr[index], max))
#call to function
lengthOfLongestSubstring("aabcdefffgges")
Error: " lengthOfLongestSubstring() missing 1 required positional argument: 's' "
Look at how you define this function:
def lengthOfLongestSubstring(self, s):
This requires two arguments, but when you call it, you only pass one:
lengthOfLongestSubstring("aabcdefffgges")
In this case, you can solve the problem by not using a class. It isn't needed for what you are doing. This also means you need to remove the self parameter from lengthOfLongestSubstring():
def lengthOfLongestSubstring(s):
arr = [char1 for char1 in s]
help_arr = [i*0 for i in range(26)]
sub_strings = []
sub = ""
for char in s:
index = ord(char) - ord('a')
if help_arr[index] == 0:
help_arr[index] = int(1)
sub += char
else:
sub_strings.append(sub)
sub = ""
sub += char
help_arr = [i * 0 for i in range(26)]
help_arr[index] = int(1)
max(sub_strings)
def max(arr):
max = 0
index = -1
for i in range(len(arr)):
if len(arr[i]) > max:
max = len(arr[i])
index= i
print("The answer is '{}', with the length of {}.".format(arr[index], max))
#call to function
lengthOfLongestSubstring("aabcdefffgges")
On a side note, you should not do return print(...). return here doesn't do anything useful, so I removed id.

Implementing Knuth-Morris-Pratt (KMP) algorithm for string matching with Python

I am following Cormen Leiserson Rivest Stein (clrs) book and came across "kmp algorithm" for string matching. I implemented it using Python (as-is).
However, it doesn't seem to work for some reason. where is my fault?
The code is given below:
def kmp_matcher(t,p):
n=len(t)
m=len(p)
# pi=[0]*n;
pi = compute_prefix_function(p)
q=-1
for i in range(n):
while(q>0 and p[q]!=t[i]):
q=pi[q]
if(p[q]==t[i]):
q=q+1
if(q==m):
print "pattern occurs with shift "+str(i-m)
q=pi[q]
def compute_prefix_function(p):
m=len(p)
pi =range(m)
pi[1]=0
k=0
for q in range(2,m):
while(k>0 and p[k]!=p[q]):
k=pi[k]
if(p[k]==p[q]):
k=k+1
pi[q]=k
return pi
t = 'brownfoxlazydog'
p = 'lazy'
kmp_matcher(t,p)
This is a class I wrote based on CLRs KMP algorithm, which contains what you are after. Note that only DNA "characters" are accepted here.
class KmpMatcher(object):
def __init__(self, pattern, string, stringName):
self.motif = pattern.upper()
self.seq = string.upper()
self.header = stringName
self.prefix = []
self.validBases = ['A', 'T', 'G', 'C', 'N']
#Matches the motif pattern against itself.
def computePrefix(self):
#Initialize prefix array
self.fillPrefixList()
k = 0
for pos in range(1, len(self.motif)):
#Check valid nt
if(self.motif[pos] not in self.validBases):
self.invalidMotif()
#Unique base in motif
while(k > 0 and self.motif[k] != self.motif[pos]):
k = self.prefix[k]
#repeat in motif
if(self.motif[k] == self.motif[pos]):
k += 1
self.prefix[pos] = k
#Initialize the prefix list and set first element to 0
def fillPrefixList(self):
self.prefix = [None] * len(self.motif)
self.prefix[0] = 0
#An implementation of the Knuth-Morris-Pratt algorithm for linear time string matching
def kmpSearch(self):
#Compute prefix array
self.computePrefix()
#Number of characters matched
match = 0
found = False
for pos in range(0, len(self.seq)):
#Check valid nt
if(self.seq[pos] not in self.validBases):
self.invalidSequence()
#Next character is not a match
while(match > 0 and self.motif[match] != self.seq[pos]):
match = self.prefix[match-1]
#A character match has been found
if(self.motif[match] == self.seq[pos]):
match += 1
#Motif found
if(match == len(self.motif)):
print(self.header)
print("Match found at position: " + str(pos-match+2) + ':' + str(pos+1))
found = True
match = self.prefix[match-1]
if(found == False):
print("Sorry '" + self.motif + "'" + " was not found in " + str(self.header))
#An invalid character in the motif message to the user
def invalidMotif(self):
print("Error: motif contains invalid DNA nucleotides")
exit()
#An invalid character in the sequence message to the user
def invalidSequence(self):
print("Error: " + str(self.header) + "sequence contains invalid DNA nucleotides")
exit()
You might want to try out my code:
def recursive_find_match(i, j, pattern, pattern_track):
if pattern[i] == pattern[j]:
pattern_track.append(i+1)
return {"append":pattern_track, "i": i+1, "j": j+1}
elif pattern[i] != pattern[j] and i == 0:
pattern_track.append(i)
return {"append":pattern_track, "i": i, "j": j+1}
else:
i = pattern_track[i-1]
return recursive_find_match(i, j, pattern, pattern_track)
def kmp(str_, pattern):
len_str = len(str_)
len_pattern = len(pattern)
pattern_track = []
if len_pattern == 0:
return
elif len_pattern == 1:
pattern_track = [0]
else:
pattern_track = [0]
i = 0
j = 1
while j < len_pattern:
data = recursive_find_match(i, j, pattern, pattern_track)
i = data["i"]
j = data["j"]
pattern_track = data["append"]
index_str = 0
index_pattern = 0
match_from = -1
while index_str < len_str:
if index_pattern == len_pattern:
break
if str_[index_str] == pattern[index_pattern]:
if index_pattern == 0:
match_from = index_str
index_pattern += 1
index_str += 1
else:
if index_pattern == 0:
index_str += 1
else:
index_pattern = pattern_track[index_pattern-1]
match_from = index_str - index_pattern
Try this:
def kmp_matcher(t, d):
n=len(t)
m=len(d)
pi = compute_prefix_function(d)
q = 0
i = 0
while i < n:
if d[q]==t[i]:
q=q+1
i = i + 1
else:
if q != 0:
q = pi[q-1]
else:
i = i + 1
if q == m:
print "pattern occurs with shift "+str(i-q)
q = pi[q-1]
def compute_prefix_function(p):
m=len(p)
pi =range(m)
k=1
l = 0
while k < m:
if p[k] <= p[l]:
l = l + 1
pi[k] = l
k = k + 1
else:
if l != 0:
l = pi[l-1]
else:
pi[k] = 0
k = k + 1
return pi
t = 'brownfoxlazydog'
p = 'lazy'
kmp_matcher(t, p)
KMP stands for Knuth-Morris-Pratt it is a linear time string-matching algorithm.
Note that in python, the string is ZERO BASED, (while in the book the string starts with index 1).
So we can workaround this by inserting an empty space at the beginning of both strings.
This causes four facts:
The len of both text and pattern is augmented by 1, so in the loop range, we do NOT have to insert the +1 to the right interval. (note that in python the last step is excluded);
To avoid accesses out of range, you have to check the values of k+1 and q+1 BEFORE to give them as index to arrays;
Since the length of m is augmented by 1, in kmp_matcher, before to print the response, you have to check this instead: q==m-1;
For the same reason, to calculate the correct shift you have to compute this instead: i-(m-1)
so the correct code, based on your original question, and considering the starting code from Cormen, as you have requested, would be the following:
(note : I have inserted a matching pattern inside, and some debug text that helped me to find logical errors):
def compute_prefix_function(P):
m = len(P)
pi = [None] * m
pi[1] = 0
k = 0
for q in range(2, m):
print ("q=", q, "\n")
print ("k=", k, "\n")
if ((k+1) < m):
while (k > 0 and P[k+1] != P[q]):
print ("entered while: \n")
print ("k: ", k, "\tP[k+1]: ", P[k+1], "\tq: ", q, "\tP[q]: ", P[q])
k = pi[k]
if P[k+1] == P[q]:
k = k+1
print ("Entered if: \n")
print ("k: ", k, "\tP[k]: ", P[k], "\tq: ", q, "\tP[q]: ", P[q])
pi[q] = k
print ("Outside while or if: \n")
print ("pi[", q, "] = ", k, "\n")
print ("---next---")
print ("---end for---")
return pi
def kmp_matcher(T, P):
n = len(T)
m = len(P)
pi = compute_prefix_function(P)
q = 0
for i in range(1, n):
print ("i=", i, "\n")
print ("q=", q, "\n")
print ("m=", m, "\n")
if ((q+1) < m):
while (q > 0 and P[q+1] != T[i]):
q = pi[q]
if P[q+1] == T[i]:
q = q+1
if q == m-1:
print ("Pattern occurs with shift", i-(m-1))
q = pi[q]
print("---next---")
print("---end for---")
txt = " bacbababaabcbab"
ptn = " ababaab"
kmp_matcher(txt, ptn)
(so this would be the correct accepted answer...)
hope that it helps.

How could I write this function the pythonic way? [duplicate]

I have a string like '....(((...((...' for which I have to generate another string 'ss(4)h5(3)ss(3)h2(2)ss(3)'.
'.' corresponds to 'ss' and the number of continous '.' is in the bracket.
'(' corresponds to 'h5' and the number of continuos '(' is in the bracket.
Currently I'm able to get the output 'ss(4)h5(3)ss(3)' and my code ignores the last two character sequences.
This is what I have done so far
def main():
stringInput = raw_input("Enter the string:")
ssCount = 0
h5Count = 0
finalString = ""
ssString = ""
h5String = ""
ssCont = True
h5Cont = True
for i in range(0, len(stringInput), 1):
if stringInput[i] == ".":
h5Cont = False
if ssCont:
ssCount = ssCount + 1
ssString = "ss(" + str(ssCount) + ")"
ssCont = True
else:
finalString = finalString + ssString
ssCont = True
ssCount = 1
elif stringInput[i] == "(":
ssCont = False
if h5Cont:
h5Count = h5Count + 1
h5String = "h5(" + str(h5Count) + ")"
h5Cont = True
else:
finalString = finalString + h5String
h5Cont = True
h5Count = 1
print finalString
main()
How to modify the code to get the desired output?
I don’t know about modifying your existing code, but to me this can be done very succinctly and pythonically using itertools.groupby. Note that I’m not sure if the 'h2' in your expected output is a typo or if it should be 'h5', which I’m assuming.
from itertools import chain, groupby
string = '....(((...((...'
def character_count(S, labels): # this allows you to customize the labels you want to use
for K, G in groupby(S):
yield labels[K], '(', str(sum(1 for c in G)), ')' # sum() counts the number of items in the iterator G
output = ''.join(chain.from_iterable(character_count(string, {'.': 'ss', '(': 'h5'}))) # joins the components into a single string
print(output)
# >>> ss(4)h5(3)ss(3)h5(2)ss(3)
#Kelvin 's answer is great, however if you want to define a function yourself, you could do it like this:
def h5ss(x):
names = {".": "ss", "(": "h5"}
count = 0
current = None
out = ""
for i in x:
if i == current:
count += 1
else:
if current is not None:
out += "{}({})".format(names[current], count)
count = 1
current = i
if current is not None:
out += "{}({})".format(names[current], count)
return out

Categories

Resources