How can I write the following script in Python? - python-3.x

So the program that I wanna write is about adding two strings S1 and S2 who are made of int.
example: S1='129782004977', S2='754022234930', SUM='883804239907'
So far I've done this but still it has a problem because it does not rive me the whole SUM.
def addS1S2(S1,S2):
N=abs(len(S2)-len(S1))
if len(S1)<len(S2):
S1=N*'0'+S1
if len(S2)<len(S1):
S2=N*'0'+S2
#the first part was to make the two strings with the same len.
S=''
r=0
for i in range(len(S1)-1,-1,-1):
s=int(S1[i])+int(S2[i])+r
if s>9:
r=1
S=str(10-s)+S
if s<9:
r=0
S=str(s)+S
print(S)
if r==1:
S=str(r)+S
return S

This appears to be homework, so I will not give full code but just a few pointers.
There are three problems with your algorithm. If you fix those, then it should work.
10-s will give you negative numbers, thus all those - signs in the sum. Change it to s-10
You are missing all the 9s. Change if s<9: to if s<=9:, or even better, just else:
You should not add r to the string in every iteration, but just at the very end, after the loop.
Also, instead of using those convoluted if statements to check r and substract 10 from s you can just use division and modulo instead: r = s/10 and s = s%10, or just r, s = divmod(s, 10).
If this is not homework: Just use int(S1) + int(S2).

Related

Calculation of time and space complexity

I am working on this Leetcode problem - "Given a string containing digits from 2-9 inclusive, return all possible letter combinations that the number could represent. Return the answer in any order.
A mapping of digit to letters (just like on the telephone buttons) is given below.
Note that 1 does not map to any letters."
This is a recursive solution to the problem that I was able to understand, but I am not able to figure out the time and space complexity of the solution.
if not len(digits):
return []
res = []
my_dict = {
'2':'abc',
'3':'def',
'4':'ghi',
'5':'jkl',
'6':'mno',
'7':'pqrs',
'8':'tuv',
'9':'wxyz'
}
if len(digits) == 1:
return list(my_dict[digits[0]])
my_list = my_dict[digits[0]] #string - abc
for i in range(len(my_list)): # i = 0,1,2
for item in self.letterCombinations(digits[1:]):
print(item)
res.append(my_list[i] + item)
return res
Any help or explanation regarding calculating time and space complexity for this solution would be helpful. Thank you.
With certain combinatorial problems, the time and space complexity can become dominated by the size of the output. Looking at the loops and function calls, the work being done in the function is one string concatenation and one append for each element of the output. There's also up to 4 repeated recursive calls to self.letterCombinations(digits[1:]): assuming these aren't cached, we need to add in the extra repeated work being done there.
We can write a formula for the number of operations needed to solve the problem when len(digits) == n. If T(n) is the number of steps, and A(n) is the length of the answer array, we get T(n) = 4*T(n-1) + n*A(n) + O(1). We get an extra multiplicative factor of n on A(n) because string concatenation is linear time; an implementation with lists and str.join() would avoid that.
Since A(n) is upper-bounded by 4^n, and T(1) is a constant, this gives T(n) = O(n * (4^n)); the space complexity here is also O(n * (4^n)), given 4^n strings of length n.
One possibly confusing part of complexity analysis is that it's usually a worst-case analysis unless specified otherwise. That's why we use 4 instead of 3 here: if any input could give 4^n results, we use that figure, even though many digit inputs would give closer to 3^n results.

Python ord() and chr()

I have:
txt = input('What is your sentence? ')
list = [0]*128
for x in txt:
list[ord(x)] += 1
for x in list:
if x >= 1:
print(chr(list.index(x)) * x)
As per my understanding this should just output every letter in a sentence like:
))
111
3333
etc.
For the string "aB)a2a2a2)" the output is correct:
))
222
B
aaaa
For the string "aB)a2a2a2" the output is wrong:
)
222
)
aaaa
I feel like all my bases are covered but I'm not sure what's wrong with this code.
When you do list.index(x), you're searching the list for the first index that value appears. That's not actually what you want though, you want the specific index of the value you just read, even if the same value occurs somewhere else earlier in the list too.
The best way to get indexes along side values from a sequence is with enuemerate:
for i, x in enumerate(list):
if x >= 1:
print(chr(i) * x)
That should get you the output you want, but there are several other things that would make your code easier to read and understand. First of all, using list as a variable name is a very bad idea, as that will shadow the builtin list type's name in your namespace. That makes it very confusing for anyone reading your code, and you even confuse yourself if you want to use the normal list for some purpose and don't remember you've already used it for a variable of your own.
The other issue is also about variable names, but it's a bit more subtle. Your two loops both use a loop variable named x, but the meaning of the value is different each time. The first loop is over the characters in the input string, while the latter loop is over the counts of each character. Using meaningful variables would make things a lot clearer.
Here's a combination of all my suggested fixes together:
text = input('What is your sentence? ')
counts = [0]*128
for character in text:
counts[ord(character)] += 1
for index, count in enumerate(counts):
if count >= 1:
print(chr(index) * count)

Is there anything else used instead of slicing the String?

This is one of the practice problems from Problem solving section of Hackerrank. The problem statement says
Steve has a string of lowercase characters in range ascii[ā€˜aā€™..ā€™zā€™]. He wants to reduce the string to its shortest length by doing a series of operations. In each operation he selects a pair of adjacent lowercase letters that match, and he deletes them.
For example : 'aaabbccc' -> 'ac' , 'abba' -> ''
I have tried solving this using slicing of strings but this gives me timeout runtime error on larger strings. Is there anything else to be used?
My code:
s = list(input())
i=1
while i<len(s):
if s[i]==s[i-1]:
s = s[:i-1]+s[i+1:]
i = i-2
i+=1
if len(s)==0:
print("Empty String")
else:
print(''.join(s))
This gives me terminated due to timeout message.
Thanks for your time :)
Interning each new immutable string can be expensive,
as it has O(N) linear cost with the length of the string.
Consider processing "aa" * int(1e6).
You will write on the order of 1e12 characters to memory
by the time you're finished.
Take a moment (well, take linear time) to
copy each character over to a mutable list element:
[c for c in giant_string]
Then you can perform dup processing by writing a tombstone
of "" to each character you wish to delete,
using just constant time.
Finally, in linear time you can scan through the survivors using "".join( ... )
One other possible solution is to use regex. The pattern ([a-z])\1 matches a duplicate lowercase letter. The implementation would involve something like this:
import re
pattern = re.compile(r'([a-z])\1')
while pattern.search(s): # While match is found
s = pattern.sub('', s) # Remove all matches from "s"
I'm not an expert at efficiency, but this seems to write fewer strings to memory than your solution. For the case of "aa" * int(1e6) that J_H mentioned, it will only write one, thanks to pattern.sub replacing all occurances at once.

Python get character position matches between 2 strings

I'm looking to encode text using a custom alphabet, while I have a decoder for such a thing, I'm finding encoding more difficult.
Attempted string.find, string.index, itertools and several loop attempts. I would like to take the position, convert it to integers to add to a list. I know its something simple I'm overlooking, and all of these options will probably yield a way for me to get the desired results, I'm just hitting a roadblock for some reason.
alphabet = '''h8*jklmnbYw99iqplnou b'''
toencode = 'You win'
I would like the outcome to append to a list with the integer position of the match between the 2 string. I imagine the output to look similar to this:
[9,18,19,20,10,13,17]
Ok, I just tried a bit harder and got this working. For anyone who ever wants to reference this, I did the following:
newlist = []
for p in enumerate(flagtext):
for x in enumerate(alphabet):
if p[1] == x[1]:
newlist.append(x[0])
print newlist

Converting between a number to a string without num2str

For example, input is a=5678. How do you make b='5678'? (b is a String).
Not allowed to use str2num or any casting.
Is it possible to use log10? (I know how to do the reverse action).
[This is how I did the opposite (from string to num):
s = input('Enter a number: ','s');
x = sum(10.^(length(s-'0')-1:-1:0).*(s-'0'));
This looks like homework, so first here are some hints:
log10 may be useful to determine the number of digits.
mod can help to obtain each digit.
From your code for the reverse action: using successive powers of 10, as well as +'0' / -'0' to convert between digits and ASCII codes, may also be of help here.
And here's a possible approach using these hints (hover the mouse to find out):
b = char(mod(floor(a./10.^((ceil(log10(a))-1):-1:0)),10) + '0'):

Resources