Fill Alphabets - Word by Word using python - python-3.x

The program must accept a string S containing multiple words as the input.The program must form a new string W based on the following conditions. - The number of words in S and W must be equal. - The length of each word in S and W must be equal. - The alphabets in W must be filled word by word from the alphabets in S. Finally, the program must print the string W as the output.
Boundary Condition(s): 0 <= Length of S <= 1000 1 <= Length of each word in S <= 20

Here is a not optimized version. There probably is a shorter version with map or lambda but ...
def shuffle(S):
words = S.split(' ')
letters = sorted([c for c in S if c != ' '])
new_words = []
i = 0
for l in letters:
placed = False
while not placed:
if len(new_words) < len(words):
new_words.append(l)
placed = True
else:
if len(new_words[i]) < len(words[i]):
new_words[i] += l
placed = True
i += 1
if i == len(words):
i = 0
return ' '.join(new_words)

Related

How to iterate faster through a loop with a range that goes to at least 2 digits (10) until 1000 digits (10^100) using Python 3 +?

I receive a non-empty string S of at most 1000 characters and an integer N (1 ≤ N ≤ 1000). Each character of S is either a decimal digit or the character “ ? ”; the leftmost character is not “ 0 ” and at least one character is “ ? ”.
I have to show an integer D without leading zeros indicating the smallest multiple of N that has | S | digits and such that the digits in S are coincident with the corresponding digits in D. If there exists no such an integer D, i write an “ * ”.
So, i managed to write a code that kind do that, but it takes forever for large numbers, i want to find a way to make it faster or if i can improve my code.
Here its an example of input and output:
input: 1??????????????????????????????? 2 / output: 10000000000000000000000000000000
input: ???????????????????????????????1 2 / output: *
input: ?294?? 17 / output: 129404
my code:
D, N = input().split()
lenOfD = len(D)
lowerD = ''
higherD = ''
infos = {}
for index, letter in enumerate(D):
if letter.isdigit():
lowerD += letter
higherD += letter
infos[index] = letter
else:
if index == 0:
lowerD += '1'
higherD += '9'
else:
lowerD += '0'
higherD += '9'
rest = int(lowerD) % int(N)
quotient = int(int(lowerD) / int(N))
if rest != 0:
while True:
result = quotient * int(N)
resultString = str(result)
matchInfo = 0
if len(resultString) == lenOfD:
newRest = result % int(N)
if newRest == 0:
for position, value in infos.items():
if resultString[position] == value:
matchInfo += 1
quotient += 1
if result > int(higherD):
print('*')
break
if len(infos) == matchInfo:
print(result)
break
else:
print(lowerD)
and still have a minor problem, that when a divide a large number for a small one, the precision sucks because it approximate to scientific notation, and that is why i converted the variable quotient to int, but its not converting to the right number.

Problem with Python Code and the Functions in it

I have a Problem, I have to solve a task in Python and I dont know how to do it. The task is to define a function number_of_vowels, where the output should be the Number of vowels in a Word. With this function I have to write anotherone, many_vowels thats working with a list an a Number and where the number says how many vowels have to be at least in a word to be appended to the result list and then I have to append this Word. Thanks to everybody helping me ;D.
here is the code:
Wort = "parameter"
def number_of_vowels(Word):
result = 0
counter0 = 0
while result < 20:
if Word[counter0] == 'a' or 'e' or 'i' or 'o' or 'u':
result = result + 1
counter0 = counter0 + 1
else:
counter0 = counter0 + 1
return result
Words = []
counter1 = 0
def many_vowels(List , number):
if number_of_vowels(List[counter1]) < number:
counter1 + 1
else:
Words.append(List[counter1])
counter1 + 1
return Words
This code just gives me the answer to the letter a and not to the other vowels. For
print(number_of_vowels(Wort))
the output is: 1
but there are 4 vowels in this word
it also says: line 21, in many_vowels
IndexError: string index out of range
You're trying to call a function with wrong brackets. Function call should use round ones.
Try changing number_of_vowels[List[counter1]] with number_of_vowels(List[counter1])
This code contains some errors:
Calling for function should be using round brackets: number_of_vowels(List[counter1]) instead of number_of_vowels[List[counter1]]
doing result + 1 won't change value of the variable result, since you did not put the calculation result in the variable. use result = result + 1 (same for counters)
in number_of_vowels function, you want to scan the whole word? cause you did not use any loop, so it currently looking only at the first letter. Secondly, you put the compression in result and then add 1 to it. I'm not really sure why
edit:
Word = "parameter"
def number_of_vowels(Word):
result = 0
counter0 = 0
for index, letter in enumerate(Word):
if letter == 'a' or letter == 'e' or letter == 'i' or letter == 'o' or letter == 'u':
result = result + 1
return result
Words = []
counter1 = 0
def many_vowels(List_name , number):
for index, item in enumerate (List_name):
if number_of_vowels(item) >= number:
Words.append(item)
return Words

replace an occurrence with a distinct number every loop

The first occurrence of the character in the string will be replaced with a 1, the second occurrence with a 2, etc.
ive tried using for loop and the max function to replace the last occurence but it doesnt seem to work.
string=str(input('string: '))
x=input('character: ')
list=[]
for i in range(len(string)):
if string[i]==x:
list.append(i)
Z=str(max(list))
print(string.replace(x,Z,[::-1]))
the output should be as following
string: departmentofcomputerscience
character: e
d1partm2ntofcomput3rsci4nc5
Here's a way to do it.
Use a counter for each character in the loop, and store values in the list, then merge the list. Use the current value if not equal to the character, counter otherwise:
string=str(input('string: '))
x=input('character: ')
# Use list to store results and a counter
l = []
counter = 0
for c in string:
if c==x:
counter += 1
l.append(str(counter))
else:
l.append(c)
# Merge the resulting list into string
res = "".join(l)
# Output the result
print(res)
For the input string: departmentofcomputerscience
and the character: e
The output is
d1partm2ntofcomput3rsci4nc5
Here is another way to achieve the goal using a list and the method replace():
string = str(input('string: '))
x = input('character: ')
list = []
for i in range(len(string)):
if string[i] == x:
list.append(i) # add all indexes to replace to the list
if len(list) > 0:
j = 0
for i in range(len(list)):
j += 1
string = string.replace(string[list[i]], str(j), 1) # replace the element once at time
print(string)
For string: departmentofcomputerscience
character: e
Output: d1partm2ntofcomput3rsci4nc5
def replace(s, c):
'''
#parameter s: input string
#parameter c: input character to be replaced
#return s: where every occurence of c is
replaced by it's nth occurence
'''
so = list(s)
j = 1
for i in range(len(so)):
if so[i] == c:
so[i] = str(j)
j = j + 1
return ''.join(so)

How do you check if a given input is a palindrome?

I need to check if the input is a palindrome.
I converted the input to a string and compared the input with the reverse of the input using list slicing. I want to learn a different way without converting input to a string.
def palindrome(n):
num = str(n)
if num == num[::-1]:
return True
Assuming that n is a number, you can get digits from right to left and build a number with those digits from left to right:
n = 3102
m = n
p = 0
while m:
p = p*10 + m%10 # add the rightmost digit of m to the right of p
m //= 10 # remove the rightmost digit of m
print(p) # 2013
Hence the function:
def palindrome(n):
m = n
p = 0
while m:
p = p*10 + m%10
m //= 10
return p == n
Note that:
if num == num[::-1]:
return True
will return None if num != num[::-1] (end of the function). You should write:
if num == num[::-1]:
return True
else:
return False
Or (shorter and cleaner):
return num == num[::-1]
There can be 2 more approaches to that as follows:
Iterative Method: Run loop from starting to length/2 and check first character to last character of string and second to second last one and so on. If any character mismatches, the string wouldn’t be palindrome.
Sample Code Below:
def isPalindrome(str):
for i in xrange(0, len(str)/2):
if str[i] != str[len(str)-i-1]:
return False
return True
One Extra Variable Method: In this method, user take a character of string one by one and store in a empty variable. After storing all the character user will compare both the string and check whether it is palindrome or not.
Sample Code Below:
def isPalindrome(str):
w = ""
for i in str:
w = i + w
if (str==w):
return True
return False
You can try the following approach:
Extract all the digits from the number n
In each iteration, append the digit to one list (digits) and at that digit at the beginning of another list (reversed_digits)
Once all digits have been extracted, compare both lists
def palindrome(n):
digits = []
reversed_digits = []
while n > 0:
digit = n % 10
digits.append(digit)
reversed_digits.insert(0, digit)
n //= 10
return digits == reversed_digits
Note: this might not be the most efficient way to solve this problem, but I think it is very easy to understand.

Anagram of String 2 is Substring of String 1

How to find that any anagram of String 1 is sub string of String 2?
Eg :-
String 1 =rove
String 2=stackoverflow
So it will return true as anagram of "rove" is "over" which is sub-string of String 2
On edit: my first answer was quadratic in the worst case. I've tweaked it to be strictly linear:
Here is an approach based on the notion of a sliding window: Create a dictionary keyed by the letters of the first dictionary with frequency counts of the letters for the corresponding values. Think of this as a dictionary of targets which need to be matched by m consecutive letters in the second string, where m is the length of the first string.
Start by processing the first m letters in the second string. For each such letter if it appears as a key in the target dictionary decrease the corresponding value by 1. The goal is to drive all target values to 0. Define discrepancy to be the sum of the absolute values of the values after processing the first window of m letters.
Repeatedly do the following: check if discrepancy == 0 and return Trueif it does. Otherwise -- take the character m letters ago and check if it is a target key and if so -- increase the value by 1. In this case, this either increases or decreases the discrepancy by 1, adjust accordingly. Then get the next character of the second string and process it as well. Check if it is a key in the dictionary and if so adjust the value and the discrepancy as appropriate.
Since there are no nested loop and each pass through the main loop involves just a few dictionary lookups, comparisons, addition and subtractions, the overall algorithm is linear.
A Python 3 implementation (which shows the basic logic of how the window slides and the target counts and discrepancy are adjusted):
def subAnagram(s1,s2):
m = len(s1)
n = len(s2)
if m > n: return false
target = dict.fromkeys(s1,0)
for c in s1: target[c] += 1
#process initial window
for i in range(m):
c = s2[i]
if c in target:
target[c] -= 1
discrepancy = sum(abs(target[c]) for c in target)
#repeatedly check then slide:
for i in range(m,n):
if discrepancy == 0:
return True
else:
#first process letter from m steps ago from s2
c = s2[i-m]
if c in target:
target[c] += 1
if target[c] > 0: #just made things worse
discrepancy +=1
else:
discrepancy -=1
#now process new letter:
c = s2[i]
if c in target:
target[c] -= 1
if target[c] < 0: #just made things worse
discrepancy += 1
else:
discrepancy -=1
#if you get to this stage:
return discrepancy == 0
Typical output:
>>> subAnagram("rove", "stack overflow")
True
>>> subAnagram("rowe", "stack overflow")
False
To stress-test it, I downloaded the complete text of Moby Dick from Project Gutenberg. This has over 1 million characters. "Formosa" is mentioned in the book, hence an anagram of "moors" appears as a substring of Moby Dick. But, not surprisingly, no anagram of "stackoverflow" appears in Moby Dick:
>>> f = open("moby dick.txt")
>>> md = f.read()
>>> f.close()
>>> len(md)
1235186
>>> subAnagram("moors",md)
True
>>> subAnagram("stackoverflow",md)
False
The last call takes roughly 1 second to process the complete text of Moby Dick and verify that no anagram of "stackoverflow" appears in it.
Let L be the length of String1.
Loop over String2 and check if each substring of length L is an anagram of String1.
In your example, String1 = rove and String2 = stackoverflow.
stackoverflow
stac and rove are not anagrams, so move to the next substring of length L.
stackoverflow
tack and rove are not anagrams, and so on till you find the substring.
A faster method would be to check if the last letter in the current substring is present in String1 i.e., once you find that stac and rove are not anagrams, and see that 'c' (which is the last letter of the current substring) is not present in rove, you can simply skip that substring entirely and get the next substring from 'k'.
i.e. stackoverflow
stac and rove are not anagrams. 'c' is not present in 'rove', so simply skip over this substring and check from 'k':
stackoverflow
This will significantly reduce the number of comparisons.
Edit:
Here is a Python 2 implementation of the method explained above.
NOTE: This implementation works under the assumption that all characters in both strings are in lowercase and they consist only of the characters a -z.
def isAnagram(s1, s2):
c1 = [0] * 26
c2 = [0] * 26
# increase character counts for each string
for i in s1:
c1[ord(i) - 97] += 1
for i in s2:
c2[ord(i) - 97] += 1
# if the character counts are same, they are anagrams
if c1 == c2:
return True
return False
def isSubAnagram(s1, s2):
l = len(s1)
# s2[start:end] represents the substring in s2
start = 0
end = l
while(end <= len(s2)):
sub = s2[start:end]
if isAnagram(s1, sub):
return True
elif sub[-1] not in s1:
start += l
end += l
else:
start += 1
end += 1
return False
Output:
>>> print isSubAnagram('rove', 'stackoverflow')
True
>>> print isSubAnagram('rowe', 'stackoverflow')
False
It can be done in O(n^3) pre-processing, and O(klogk) per query where: n is the size of the "given string" (string 2 in your example) and k is the size of the query (string 1 in your example).
Pre process:
For each substring s of string2: //O(n^2) of those
sort s
store s in some data base (hash table, for example)
Query:
given a query q:
sort q
check if q is in the data base
if it is - it's an anagram of some substring
otherwise - it is not.
This answer assumes you are going to check multiple "queries" (string 1's) for a single string (string 2), and thus tries to optimize the complexity for each query.
As discussed in comments, you can do the pro-process step lazily - that means, when you first encounter a query of length k insert to the DS all substrings of length k, and proceed as original suggestion.
You may need to create all the possible combination of String1 that is rove like rove,rvoe,reov.. Then check this any of this combination is in String2.
//Two string are considered and check whether Anagram of the second string is
//present in the first string as part of it (Substring)
//e.g. 'atctv' 'cat' will return true as 'atc' is anagram of cat
//Similarly 'battex' is containing an anagram of 'text' as 'ttex'
public class SubstringIsAnagramOfSecondString {
public static boolean isAnagram(String str1, String str2){
//System.out.println(str1+"::" + str2);
Character[] charArr = new Character[str1.length()];
for(int i = 0; i < str1.length(); i++){
char ithChar1 = str1.charAt(i);
charArr[i] = ithChar1;
}
for(int i = 0; i < str2.length(); i++){
char ithChar2 = str2.charAt(i);
for(int j = 0; j<charArr.length; j++){
if(charArr[j] == null) continue;
if(charArr[j] == ithChar2){
charArr[j] = null;
}
}
}
for(int j = 0; j<charArr.length; j++){
if(charArr[j] != null)
return false;
}
return true;
}
public static boolean isSubStringAnagram(String firstStr, String secondStr){
int secondLength = secondStr.length();
int firstLength = firstStr.length();
if(secondLength == 0) return true;
if(firstLength < secondLength || firstLength == 0) return false;
//System.out.println("firstLength:"+ firstLength +" secondLength:" + secondLength+
//" firstLength - secondLength:" + (firstLength - secondLength));
for(int i = 0; i < firstLength - secondLength +1; i++){
if(isAnagram(firstStr.substring(i, i+secondLength),secondStr )){
return true;
}
}
return false;
}
public static void main(String[] args) {
System.out.println("isSubStringAnagram(xyteabc,ate): "+ isSubStringAnagram("xyteabc","ate"));
}
}

Resources