With reference to single-row-keyboard.
The problem says:
Given a string keyboard of length 26 indicating the layout of the
keyboard (indexed from 0 to 25), initially your finger is at index 0.
To type a character, you have to move your finger to the index of the
desired character. The time taken to move your finger from index i to
index j is |i - j|.
Input: keyboard = "abcdefghijklmnopqrstuvwxyz", word = "cba"
Output: 4
Explanation: The index moves from 0 to 2 to write 'c' then to 1 to write 'b' then to 0 again to write 'a'.
Total time = 2 + 1 + 1 = 4.
This is a fairly simple problem which should not take much time. So I attempted the below solution for it.
def key_front(num, k, word, keyboard):
for x in range(k):
if word[num] == keyboard[x]:
return x
return 0
def calculateTime(keyboard, word):
k = len(keyboard)
count = 0
i = 0
w = len(word)
diff = 0
while i < w:
front = 0
front = key_front(i, k, word, keyboard)
print(front,diff,word[i],count)
if word[i] == word[i-1]:
diff = 0
diff = abs(front-diff)
count += diff
i = i + 1
return count
The point that I am using recusrion here is because there might be a case where each chareacter can appear multiple times in sequential order always.
My code fails for the below test case when such scenario occurs:
keyboard="pyevcountbgjklxfqwimrdhazs"
word="gxafwhexxykisciactyfdyfixqfchwanvmsjwycyyznpkykfkgfwpaajiqftklahgergnyxunfbmvkiyrifljolkkvcmdsimnmmdulqpirbdkhalakgsgomlnxivjqgbamnylecwmnulldjueppxptrjbyrijrqvagqklnglegiqoumqxftarrkhlkxufqhsqeacwzfonupihnjyzzwnrutdkcwtehzyjgvvsgevxewyhzhkwpoxkjjafdivqsabiayrgeytmkxtzhjeynttovyldlhfyfzwbfzaweoghgfyyblrrcqjzajmsjormweeqyzsiuqsgyoddkgzxskwpytbysvroanpplwjnucowvwdhimvjnosezxhrxswxlfyfqmiuyvrbngigbldvbejqlrnqffkhjdftnkgusegtpasapuwldmlmnxzxhckopukczpsbkqjdhonydgjdlfpldqawrzqojjulizkwvaoxykzmrupoaafwpvexihbrjjwxtzbjvdfqwrajuvlnxudwpqqqvzvfmfvesrqqfvugqhtavwemmonxwnmhblutoaafvbvkuhgbjnduwtsckhjnsnlmfaghqejyzmibbwzflskzfcycnjpebsmlihbetehuomyyhnnqthonqtxigfioarksrhwgjiirlwnaqnadbyrvtyxhrsezkdkfgawlfuchsugturgibjozlplqymlczcbmybntqosaxpmqijcljyqrkocsjvaqdqsfqfhmdzxudqvsxbsvgijquzbxktwqgexjiqgkbdowmjypybkprxmmhzhnogjhzpbgrkphqywunzeijgqzreonyrkheeoltbruxndrdnhuwstxsdzhnoqmngtbjynlijjlbopnderookdpcdqeqtkwrqdiplysdjvojhxylxcxqrjtdirwswdtlvrytdxrlwhmdegsqmhaazhdtozzwomgbwppcfbyhwmpzobvpnqbmzvtqworqlnuthhfkshbgpohlhopedlvfuuqcmsgewtkuuxocdzyejbhmihjjgdxaspcthpwtxzzvzxitemwjbquuepgcqpgilpsekkendrpxzfmfdjtelrhjiqbmofjarzywltvbjhjpcitoatpcnhovanuuvlcnhkfedzksmhywcnlslamdztgitssswkbgmdkjzqjioxontjluwfkyaejkvquqcixbcicxbgreyzdkgnxspuxusudyxqlojhifwpfziqjhgyharrsyhqacnlewifrxgggvxhfaqjcthzhspvyrxswmvkwkyqgfaltzgqyoemgqbxquufjalezvvjdurcazdirrljhauabesfkpzkskbwzrluazbovmveecgkwwpzxqrpwxfsiukjpfzxryndoofohvvramxfdbtyqzcstqjesshrcygtctkymeimreyszmddhqxyqurcxlnkksylixnfgrswwvrsrqpknvvcnhimbklsixqmdmcnmzrnbdswtfyuqnzlsqwqgologslbpokjudvvyvzcaxyaepdwtwdndslhswhnbpmphasxkglrukhmbjssdcgkiohelcdvoofvucgqotqiwmgxynjuggscsahqocuutariwloclmwigjbejrxvujxtjvbmgvfhpowxmniruncakpunfhjkunrzzzdteqomdsvjoegijuyggwjjibovzjjeycpvnmupdosrcsdvblhtvrykqljkhtbdboxwfzyhmuyqnaxctkfmiqogqqbvhkourtjahbqnnkvifsxdxqtcolgvqlrujumzgqcoxifwrrfgpyfgmlqpnamcvkjjjwybzgbyooatvnzpxdvloxivkrvtjbnnbqwtbrsfdswtknbaaggqcuclaxwqsoeuxunnnzfbsgmhpcpktiluazzkzaivzgyttccbpptaegucsbvirrafwxrkbconutpwsusseutxrypzhmvttvpftdbjhkfhctphrbzoszatydweonydryatfsibdhjwhegptkcikinentiazxugcdlpzmdayxjsgcjqtkdfvbkpmmiyjzyiwpvqsooucnmpquxbpjhltxmiqxhbcmoesxhdcpbuukosxnzmizsigrzdgtkpuprnpogpmegojfdwvupldjtglnkbszsmhnrhlqpkbtfulyfuqliovvovtcmayoqyxujrpwndfbzsmftpksoyoepkmablhiunnuybawetbvojblrgmenxfpmiomhgpqpyjrpvhrslxgnfhsajnfjslfiuoybumzmbigxkmmobsusdyzzuyrzieoxdrtescnnwxmleriqrbxwimfqqwnakfangowwauvoqtoxklvtvmyyjwvjcfrwtbxwrhvnatndbtvxxmprqkyjltmprfdasdhpgbkpeqmtzbqiuivwvxhpmcsnfgbejwewwilhfutrirbvmxnhsypoqhlptwqouawletsdklwusgyfjrlvrpwnionjtljnehbzyfxgveedbefowrzmnovtpiyfoemirwrfkmilpupmmldkoyjrbwmbjhnwunrmfrgovfwnkrcxkqjxscgpqxrgikqskqzwfqwnpebizmyuzqykoosskuveznhbohhdseshqniuocdxkbpwdkoyozmajyrhnppldvaltuscbhsqowpzsvlqrfjuvsrdsamqqqacxkzsxnbamqeoxnkevrelayinwdaypcxwiycpuktbdhxehpcatddkocanpgjmdglnoamallknslqdmyxilnmsddotlfztmurzmsiebwpgqkmmqyexclykoxawiidaykmalwjyrsmoumrsbhnqxjkqopwqipzqrnxdixqkqjbsbttdddyryccaccfafaqeumjeeryqteenfjmiyyauvgvagltgsndfrsxkasimlveesfxoqlynjabtzryosvhkdnodqnsgezkgrzidceyzisyryrhjkysjnqyswylbejrahoxvvhcscnqgdsaahvmldnphmwogikjyrauonlztpgyqcwylhzmbwdztdpahusbysqplhimbltdvtycqxisnipapxeoqtlhtkvivnwbhfgmxhdcaiqdmpxfuqoxtxakwswdnqycjwqwryirnxqgohnbbqogobroifsmwjtjzdzrtulkjynqxbnoyjbwosfodnbcdauosglhsjqfcnnbsarxxgkhbtxbdloukycpcoypvxogmfcerljogtrlzcqrlogulbiyfsesjybmmdytlmkbwefuvsmtjcojfxpapkqjwvhtyqwmzxdystgozdgogqbdqhvlkspuxxqfiacdvnzhibgfzuzakqqswoacytfsdhzesxksgimhwkvddzfyakjmzlgknmndytphqaunghtuhjkkjyicqgmjvxcutwoiqvqxfawzwuuikgjqrfdnfcqqwvwgvjffetmwcfemyuhzyvicqkezagbtrqvlsircpmaeczdujtqnlsyfumbqfouxhpmwrzaciqzfpkzkcscjaichjjsyftwjltcsnmbxsozyltyuyjbujgvsahibnagwwwkacqyrjkiftcpklkxnysytqoyhibqqpdgzmkynbwpndnsnxmarnhtwhunedneftdpenrykljvcdkknvitlyjznvaeqgdozvrxooqfgmvhnqxgrfravsxlkwlenrruibwrjoupgsqpvreryybmcuujimjqzidssolfevezfnsqmmixzsnhifjjmyjxoqzzfmmqdmomfayoguaqqhbzershztalosxventouwznjxohsekrtypunhlhhatckxnkqeujlgnoftnsteuxbdgpfwywhfmwszecborzrhgbeymiluidtrksraewipnjlcsngbjfxsjrofyroxdfcxsorakmefkdngohelizojjjncebhvvvphikvgippueimhwtfuedgloidjuyswvmqfvvphffxhoebbsatwswvsabbwrdbpfmvoegjlxzsguvetalhonbbsmnfafxxniadcjrmihctihttueaaumhoqivnkihelnjgntspgikzeysmiwdwwkkroblisdaddfshrcnjveeijvqdkmltmblbaifgzswboznvbmqeeqxjxlnizyydokojyrbdmmyzhdyebqzxqkohofgrvemrxorljvnfztnriartlzzikkzhbkjmpygeqpxbemnivpslvmcdrfekyrgofwcenkqtlogdptigkrgpthxiitjdsuxmlghvdsitwcuuoiaywzzdabarxouicuftepjydddlqtrcthrysgxlqebjnkreedlfqdezlkltuyhkcqguwtlzdmfdmaueafwjmrvzopqqszoluiokyoleadpgncpbbjbowtwxvfhtktqdtpuavgapekgogugcoidveqfatsnknvzsnzdijfagdvyskkaowwlacxtvynmkgckusacwbimgrlmpzfahdpkznmgapxomjqkawrtnzojjnihfjjwjvrsppiksqhqlgusmuwlomatlqpveqnmvazrwuadfiluktpsuzynmkngwwhakouaqxhohryfncgweyagjdwqkgfunhvxztdevtuioqzmepdniiysbzbkxivvpzqbyftzkakvdsconhnmycksledkiubhnvifliekqsucxivrxmpjeorrenthlfvawdnnmnujdsxdibtvvjqghxaklrubelvpufrzmshnuvmbvdbskaozdzszxuimsmjgwfexpvzqvfvbatcyyudkfmbyxdcayraydfogvmomqqriamcipkhoohvenkbcieqbzohqoejnujduwwbkmpnuzqyxnlzvbopeoasepgxgtxfimxsvzkohluzjqykzfnkdiaradcbhpqlcjqhmmuuwawynzyvzjulbkikvuerljdfrxquljjzlcjoxpgsqznuxykghydkqaybghxixeqnhtmnxlrgkcctjvnktcppnbeoocegxnwavtxxnyyqoiwihxmusviqumficjvsbsfqxszdcgboppsipnmghyaxcbzqaqfyitatqxantamritaynlahfnivgdvwexltgvpyuyqmdvhaglcbkqqbnerkwodjaniwuvippzuxambcvnjhyjngbfdctfzmdzydrhiinbzwrdjfiqjiehjexbqqdzvsqoitdfrfjauebfgklzkhrwrdcnxptrbaqzrwhlclzozixzqtsdploalrpkcbfecwakawamxqgfgxqtozyxswtpxeubtxjbcpqdxbegdjzxyqpmynsoeizdgrusdjfwxdqpgagxivuhnvbfkzyedcvuvviqdwoogjiohedhkjtmvolohkwdxivkpknrzwybvyvzgwpfmphhyikahqhcmqfgjlqtfxsmlcwityahsbscpqeizuvovzhkgjsszdnibvmkjpsgoxedclcrlvvmbuuomodgdwxlgurerxiovfdifofvohbeaqhzxlccyqopjcaiiawzqggqhiibhtcicxxnygdtimeoiiegnesserbrmczmvsctcmxtbpuuotcgilvampmbvtmocbwqbqqweanmqosttoczdmfkdtdsefeirypczqmegpzqfgiwmmvtggaggbgzsdjjupnipffyyabftxuckdcebapbhkjycdavlfgkiititnqgmykosvgfgvpienqvbftjsfhvsxnjklycalqxskwdoizdffwrszljkkvugggvicbxhslpvygssebblxugnsnwgqrsmboqtqzfjuaiyleuxycwedmjiovyzyvzsoypoohcufxftbkiffowxwhjtlnztbvwimhofnvcibzvkoneuszylbmaydsrbqaygtzqevtsufxpzijztftwniizuccexlrcfbyiiyohtbrbnlccmhmbpoxcfeeakndsllmjfazugxubpwbjqtkwuzkkjzdkwacxwosljycxfuffzbzknnbspidtbzasxlrhaeylslczfszgdrqkvcfwmuweqmoctzuyicbqpvzomtfaienpkcitijxymixqsujyovmhavxjxzckbvvemxcobkjajmqhjqxtnjhrxvefgyrowbsgizzckgbhgatqyxptdzumtgnhtevrzowkdwlleuohcceqoblzsmtnucshmwyrzvsdlgvwuxamjwyfhmxiyrlztlgzbzrgtlcohwytbrnsuftirarmubqjrmxnmkudptiaxfnwrfmiuqvyiljtjmlunchelckaigvfokttwvlnchbtpsinfvpsdzmkgfeigraosyfleiorumsaeqvgzncofcltgowmjoccnqpezjeonxghbxccldtcoykrntkyztgtspzhmenviunitoazwlvktdbgiadocnuvgxdwpwnpkrfasajtpcgeyjkbyjlgscejedhighludhpaznvgwmwzdtidotzjxisjkzprqmnwdrcqjdudzmivrkxgugcogtmaafupjqvhsagspwkdazjdjjmilpjhooubrvwxmwctgplgdsaujxdpgzhohffyafgkfxdkqsqadkwwdxjptryzjhsseqpgfdpefpbskvnfuvmtynsdzavupcdfecspnpqgfdkcnnpeoisojpftrhdppnjuloqoqrfhctrgtkmeqlzltnexeivpbfomrnftrzpaqnxpbthuqlihnoytwhelrhuhvcmiocyscxdsfqbqsfompvaxseoykbsknritjybarukxembzoowynkjxuporusjhezzwbdprmpgyxbzktiwubotwbleyzrqhnpajopklqksbfeixtvrebzrokoojpegdnrrtwlrcyfiabfauohrkeweyepfrjntxouxxghkabjbucnhzkstaafsgugjtxtzwdcvvgbwlseiqaxjissvhhxpxxarnfpwkcfbvecnlzlsomadlfabgxckuqjatvbfrddxcovnigerkzdavogizmqhyjmiyzttfxvscaaqjnjtlknyyyihfpvtierrjdybjfibvcfrpttuidtctpkaxvljturvmylgihazgtusycfgkqwmacpspiarqyumgstdbqntouptvjqmysdghtmgflzhjzwoyoxvpmaoeepzavnqpmzsszlkeiqmmhufoxahkiqvbvovdqqgojutqmrutguvusosdtfkzkmrcdeslqukzqncyfcpxsrgyzkkzemqmitqmdlfwmdvgeercsdtsmzjmnyewzmgkxncutuvfwozlifxxtxdwzufgevzrunqdhuoicvdueudxocnyruuqwylaujftanbaidzwaiaqzxcrmkshazhbaelzwnaqtkrjtexiskzrofqjzxtsjceiqldhsedyewqczqslccsrrijevqchauzkopwnmzsbjrypfdtaeycgidfhqggewingnihrnwbnmuhtayqqhlwnmmyuibwfhqgemkxgyoumtorkanclrhtupsklvhsolcejvhixmnblugbxciifmvkwauhuywvbuutzktocgcngzkvnwvrjdmoibalwxgxfbubupwisbajtuuxoxpdouqmdaezocfbpkeqezkmrugupulxgtpnlwlfunjuaatfzrggrotfsehswepguoapdpvtfgkyheqwbnpoowafotdzzowxyhxehfrekejjhzctdtqssthcmvmaznatprnjitwflwytwuwlknzwrnpnrymjeeljhyypokdjgiszpozrhojjebxjfrfoxatxhi"
Output = 66042
I've changed your code a little bit, but only to the point that it is giving correct result. If you want to optimize your code, #hiro protagonist's answer is a pretty good example to start with.
# this function is working fine
def key_front(num, k, word, keyboard):
for x in range(k):
if word[num] == keyboard[x]:
return x
return 0
def calculateTime(keyboard, word):
k = len(keyboard)
count = 0
i = 0
w = len(word)
diff = 0
# I've added a new variable here to store "your finger's" previous position:
prev_front = 0
while i < w:
# there is no need to initialize "front" here
front = key_front(i, k, word, keyboard)
print(front,diff,word[i],count)
#if word[i] == word[i-1], front and prev_front would be the same, resulting diff == 0
diff = front - prev_front
# assigning our new variable prev_front
prev_front = front
# diff might be negative so we only need it's absolute value
count += abs(diff)
i = i + 1
return count
this seems to work:
keyboard = "pyevcountbgjklxfqwimrdhazs"
word = "gxafwhexxykisc...jebxjfrfoxatxhi"
keys = {char: index for index, char in enumerate(keyboard)}
index = 0
s = 0
for char in word:
i = keys[char]
s += abs(index - i)
index = i
print(s) # 66042
i create the look-up table keys for the keyboard first, then i loop over the characters of your word, update the index i currently am and sum the absolute difference between the new ald the old index in the running sum s.
in your solution diff is always assigned to 0 and will never be any other value: you only handle the case where the current and the previous letters are the same.
also you do not seem to keep the current index you are at.
Related
string1 = "abbbcccd"
string2 = "abbbbdccc"
How do I find the number of triplets found in a string. Triplet meaning a character that appears 3 times in a row. Triplets can also overlap for example in string 2 (abbbbdccc)
The output should be:
2 < -- string 1
3 <-- string 2
Im new to python and stack overflow so any help or advice in question writing would be much appreciated.
Try iterating through the string with a while loop, and comparing if the character and the two other characters in front of that character are the same. This works for overlap as well.
string1 = "abbbcccd"
string2 = "abbbbdccc"
string3 = "abbbbddddddccc"
def triplet_count(string):
it = 0 # iterator of string
cnt = 0 # count of number of triplets
while it < len(string) - 2:
if string[it] == string[it + 1] == string[it + 2]:
cnt += 1
it += 1
return cnt
print(triplet_count(string1)) # returns 2
print(triplet_count(string2)) # returns 3
print(triplet_count(string3)) # returns 7
This simple script should work...
my_string = "aaabbcccddddd"
# Some required variables
old_char = None
two_in_a_row = False
triplet_count = 0
# Iterates through characters of a given string
for char in my_string:
# Checks if previous character matches current character
if old_char == char:
# Checks if there already has been two in a row (and hence now a triplet)
if two_in_a_row:
triplet_count += 1
two_in_a_row = True
# Resets the two_in_a_row boolean variable if there's a non-match.
else:
two_in_a_row = False
old_char = char
print(triplet_count) # prints 5 for the example my_string I've given
yamxxopd
yndfyamxx
Output: 5
I am not quite sure how to find the number of the most amount of shared characters between two strings. For example (the strings above) the most amount of characters shared together is "yamxx" which is 5 characters long.
xx would not be a solution because that is not the most amount of shared characters. In this case the most is yamxx which is 5 characters long so the output would be 5.
I am quite new to python and stack overflow so any help would be much appreciated!
Note: They should be the same order in both strings
Here is simple, efficient solution using dynamic programming.
def longest_subtring(X, Y):
m,n = len(X), len(Y)
LCSuff = [[0 for k in range(n+1)] for l in range(m+1)]
result = 0
for i in range(m + 1):
for j in range(n + 1):
if (i == 0 or j == 0):
LCSuff[i][j] = 0
elif (X[i-1] == Y[j-1]):
LCSuff[i][j] = LCSuff[i-1][j-1] + 1
result = max(result, LCSuff[i][j])
else:
LCSuff[i][j] = 0
print (result )
longest_subtring("abcd", "arcd") # prints 2
longest_subtring("yammxdj", "nhjdyammx") # prints 5
This solution starts with sub-strings of longest possible lengths. If, for a certain length, there are no matching sub-strings of that length, it moves on to the next lower length. This way, it can stop at the first successful match.
s_1 = "yamxxopd"
s_2 = "yndfyamxx"
l_1, l_2 = len(s_1), len(s_2)
found = False
sub_length = l_1 # Let's start with the longest possible sub-string
while (not found) and sub_length: # Loop, over decreasing lengths of sub-string
for start in range(l_1 - sub_length + 1): # Loop, over all start-positions of sub-string
sub_str = s_1[start:(start+sub_length)] # Get the sub-string at that start-position
if sub_str in s_2: # If found a match for the sub-string, in s_2
found = True # Stop trying with smaller lengths of sub-string
break # Stop trying with this length of sub-string
else: # If no matches found for this length of sub-string
sub_length -= 1 # Let's try a smaller length for the sub-strings
print (f"Answer is {sub_length}" if found else "No common sub-string")
Output:
Answer is 5
s1 = "yamxxopd"
s2 = "yndfyamxx"
# initializing counter
counter = 0
# creating and initializing a string without repetition
s = ""
for x in s1:
if x not in s:
s = s + x
for x in s:
if x in s2:
counter = counter + 1
# display the number of the most amount of shared characters in two strings s1 and s2
print(counter) # display 5
For an exercise, I have to create a simple profanity filter in order to learn about classes.
The filter gets initialized with a list of offensive keywords and a replacement template. Every occurrence of any of these words should be replaced with a string that is generated from the template. If the word size is shorter than the template, a substring should be used that starts from the beginning, for longer sizes, the template should be repeated as often as necessary.
The following are my results so far, with an example.
class ProfanityFilter:
def __init__(self, keywords, template):
self.__keywords = sorted(keywords, key=len, reverse=True)
self.__template = template
def filter(self, msg):
def __replace_letters__(old_word, replace_str):
replaced_word = ""
old_index = 0
replace_index = 0
while old_index <= len(old_word):
if replace_index == len(replace_str):
replace_index = 0
else:
replaced_word += replace_str[replace_index]
replace_index += 1
old_index += 1
return replaced_word
for keyword in self.__keywords:
idx = 0
while idx < len(msg):
index_l = msg.lower().find(keyword.lower(), idx)
if index_l == -1:
break
msg = msg[:index_l] + __replace_letters__(keyword, self.__template) + msg[index_l + len(keyword):]
idx = index_l + len(keyword)
return msg
f = ProfanityFilter(["duck", "shot", "batch", "mastard"], "?#$")
offensive_msg = "this mastard shot my duck"
clean_msg = f.filter(offensive_msg)
print(clean_msg) # should be: "this ?#$?#$? ?#$? my ?#$?"
The example should print:
this ?#$?#$? ?#$? my ?#$?
But it prints:
this ?#$?#$ ?#$? my ?#$?
For some reason it replaces the word "mastard" with 6 symbols instead of 7 (one for each letter). It works for the other keywords, why not for this one?
Also if you see anything else that seems off, feel free to tell me. Do keep in mind tho that I am a beginner and my "toolbox" is quite small atm.
Your problem is in the index logic. You have two errors
Each time you reach the end of the replacement string, you skip a letter in the profanity:
while old_index <= len(old_word):
if replace_index == len(replace_str):
replace_index = 0
# You don't replace a letter; you just reset the new index, but ...
else:
replaced_word += replace_str[replace_index]
replace_index += 1
old_index += 1 # ... but you still advance the old index.
The reason you didn't notice this is that you have a second bug: you run your old_index from 0 through len(old_word), which is one more character than you started with. For the canonical four-letter word (or words of 5 or 6 characters), the two errors cancel each other. You didn't see this because you didn't test enough. For instance, using:
f = ProfanityFilter(["StackOverflow", "PC"], "?#$")
offensive_msg = "StackOverflow on PC rulez!"
clean_msg = f.filter(offensive_msg)
Output:
?#$?#$?#$?# on ?#$ rulez!
The input words are 13 and 2 letters; the replacements are 11 and 3.
Fix those two errors: make old_index stay in bounds, and increment it only when you make a replacement.
while old_index < len(old_word):
if replace_index == len(replace_str):
replace_index = 0
else:
replaced_word += replace_str[replace_index]
replace_index += 1
old_index += 1
Future improvements:
Refactor this into a for loop.
Don't reset your replace_index; in fact, get rid of it. Simply use old_index % len(replace_str).
I'd do this with a regular expression instead, since re.sub() has a handy API for dynamic replacements:
import re
class ProfanityFilter:
def __init__(self, keywords, template):
# Build a regular expression that will match all of the profane words
self.keyword_re = re.compile("|".join(re.escape(keyword) for keyword in keywords), re.I)
self.template = template
def _generate_replacement(self, word):
l = len(word)
# Figure out how many times to repeat the template
repeats = (l // len(self.template)) + 1
# Since we may end up with a string longer than the original,
# slice to the correct length.
return (self.template * repeats)[:l]
def filter(self, msg):
# Replace all occurrences of the regular expression with
# a dynamically computed replacement value.
return self.keyword_re.sub(
lambda m: self._generate_replacement(m.group(0)),
msg,
)
f = ProfanityFilter(["duck", "shot", "batch", "mastard"], "?#$")
offensive_msg = "this mastard shot my duck"
print(f.filter(offensive_msg))
Couldn't make a one-liner, but here's a terrible implementation anway. Don't do what VoNWooDSoN does:
def replace(msg, keywords=["duck", "shot", "batch", "mastard"], template="?#$"):
for keyword in keywords * len(msg)):
msg = (template*len(keyword))[:len(keyword)].join([msg[:msg.find(keyword)], msg[msg.find(keyword)+len(keyword):]]) if msg.find(keyword) > 0 else msg
return msg
offensive_msg = "this mastard shot my duck"
clean_msg = replace(offensive_msg)
print(clean_msg) # should be: "this ?#$?#$? ?#$? my ?#$?"
print(clean_msg=="this ?#$?#$? ?#$? my ?#$?")
edit
So, I guess that 3.8 has assignment expressions... So, but this'd be the one liner then (probably).
print ((lambda msg: [msg := (("?#$"*len(keyword))[:len(keyword)].join([msg[:msg.find(keyword)], msg[msg.find(keyword)+len(keyword):]]) if msg.find(keyword) > 0 else msg) for keyword in ["duck", "shot", "batch", "mastard"]])("this mastard shot my duck")[-1])
In my attempt to solve the above question, I've written the following code:
Logic: Create a frequency dict for each character in the string (key= character, value= frequency of the character). If any character's frequency is greater than ceil(n/2), there is no solution. Else, print the most frequent character followed by reducing its frequency in the dict/
import math, operator
def rearrangeString(s):
# Fill this in.
n = len(s)
freqDict = {}
for i in s:
if i not in freqDict.keys():
freqDict[i] = 1
else:
freqDict[i] += 1
for j in list(freqDict.values()):
if j > math.ceil(n / 2):
return None
return maxArrange(freqDict)[:-4]
temp = ""
def maxArrange(inp):
global temp
n = len(inp)
if list(inp.values()) != [0] * n:
resCh = max(inp.items(), key=operator.itemgetter(1))[0]
if resCh is not None and resCh != temp:
inp[resCh] -= 1
# Terminates with None
temp = resCh
return resCh + str(maxArrange(inp))
# Driver
print(rearrangeString("abbccc"))
# cbcabc
print(rearrangeString("abbcccc"))
In the first try, with input abbccc, it gives the right answer, i.e. cbcabc, but fails for the input abbcccc, returning ccbcabc, without handling it using the temp variable, else returning cbcabc and skipping c altogether when handled using temp
How should I modify the logic, or is there a better approach?
Goal is to find the maximum amount of times you can subtract t from s.
t = ab, s = aabb. In the first step, we check if t is contained within s. Here, t is contained in the middle i.e. a(ab)b. So, we will remove it and the resultant will be ab and increment the count value by 1. We again check if t is contained within s. Now, t is equal to s i.e. (ab). So, we remove that from s and increment the count. So, since t is no more contained in s, we stop and print the count value, which is 2 in this case.
Problem occurs when you have something as s = 'abbabbaa' t = 'abba'.
Now it matters if you take it from the end or beggining, since you will get more steps from the end.
def MaxNum(s,t):
if not t in s:
return 0
elif s.count(t) == 1:
front = s.find(t)
sfront = s[:front] + s[front + len(t):]
return 1 + MaxNum(sfront,t)
else:
back = s.rfind(t)
front = s.find(t)
sback = s[:back] + s[back +len(t):]
sfront = s[:front] + s[front + len(t):]
print (sfront,sback)
return max(1 + MaxNum(sfront,t),1 + MaxNum(sback,t))
def foo(t,s):
return max([0] + [
1 + foo(t,s[:i]+s[i+len(t):]) for i in range(len(s)) if s[i:].startswith(t)])
Should I ask why you care?