insert multiplication operator in a string where necessary [closed] - python

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
As part of a project I am working on, I would like write to rewrite strings such that:
Multiplication should be placed in between number and letter when they are not present.
The equation should be equal to zero.
If, Input : 2x+5ydh=4 then output : 2*x+5*ydh-4
If, Input: x*3df + d5jk = -12 then output: x*3*df + d*5*jk +12
I am thinking of searching for the positions of numbers and letter separately, and then see they follow each other before fixing multiplication, but is that pythonic enough?

Why don't you do something like the following code snippet? Instead of going through and searching for the positions of each digit or letter, just perform it all in one loop, which is more efficient. Basically, we go through the string character by character. If a digit follows a letter, or vice versa, then we add a '*'. Otherwise, continue searching.
Then, to do the '=' part, just assign the negation of the right hand side to the left hand side. This part is a temporary (easy) fix, but if you want a more foolproof fix, you'd have to do some legitimate parsing and evaluating of the right hand side to negate it.
def convert(inp: str):
# Edge case check
if len(inp) == 0: return inp
# Go through the string looking for where to place '*'s
# Add the first character
tmp = [inp[0]]
for i in range(1, len(inp)):
# If letter followed by digit or the reverse, then add a '*'
if (inp[i].isalpha() and inp[i - 1].isdigit()) or (inp[i].isdigit() and inp[i - 1].isalpha()):
tmp.append('*')
# Now add the current character
tmp.append(inp[i])
# Convert the resulting list back to a string
ans = ''.join(tmp)
# Now if the equal sign is present, split the result
# and negate the right hand side
if '=' in ans:
left, right = ans.split('=', 1)
ans = '{}-({})'.format(left, right)
# Return the answer
return ans
print(convert('2x+5ydh=4'))
print(convert('x*3df + d5jk = -12'))

Try this :
a = "2x+5ydh=4"
b = "x*3df + d5jk = -12"
def format_equation(inp_str):
lst = str("".join([c + "*" if (c.isnumeric() and d.isalpha()) else (c+"*" if (c.isalpha() and d.isnumeric()) else c) for c,d in zip(inp_str,inp_str[1:])]) + inp_str[-1]).split("=")
lhs = lst[0]
rhs = "+" + str(abs(int(lst[1]))) if int(lst[1]) <0 else "-" + str(lst[1])
return lhs + rhs
format_equation(a) # 2*x+5*ydh-4
format_equation(b) # x*3*df + d*5*jk +12

Related

Get n Characters from String specified in python [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
Let s = "%2ABCDE" - get first 2 characters from string
then output should be "AB".
Need to get characters from string specified by numeral in string.
E.g. s1="%12ABCDERTYUIOPLKHGF" - get first 12 characters from string.
I tried to get digit using re.findall('\d+', string ), but this creates problem if my string would be "%2ABCD1".
Please suggest
s = "%2ABCDE"
number = ""
offset = 0
for i in range(len(s)):
if s[i] == "%":
continue
elif s[i].isdigit():
number += s[i]
else:
offset = i
break
print(s[offset:int(number) + offset])
Output: AB
A simpler way of doing this would be to do the following:
txt = "%2ABCDE"
number_list = [s for s in txt if s.isdigit()]
number_concate = int("".join(number_list))
txt_filtered = txt[len(number_list)+1:]
print(txt_filtered[:number_concate])
Outputs AB for string "%2ABCDE"
Outputs ABCDERTYUIOP for string "%12ABCDERTYUIOPLKHGF"
You are taking your string, doing a list comprehension of the string if the digit exists, then joining the list and changing this to an integer to allow for you to filter your string accordingly. Then you strip the string to only the characters and you have your answer printed out.
import re
s = '%2ABCDERTYUIOPLKHGF'
numeral_instruction = re.search(r'%\d+',s).group(0)
start = len(numeral_instruction)
stop = start + int(numeral_instruction[1:])
s[start:stop]
outputs
AB
You can get the position of the first non-digit character in the string (skipping the %) and use that as the basis to get the length and form a substring:
s1="%12ABCDERTYUIOPLKHGF"
i = next(i for i,c in enumerate(s1[1:],1) if not c.isdigit())
result = s1[i:i+int(s1[1:i])]
print(result)
ABCDERTYUIOP
If the first number in the string is not always at index 1, you can skip a variable number of characters using the same technique:
s1="*:%12ABCDERTYUIOPLKHGF"
start = next(i for i,c in enumerate(s1) if c.isdigit())
end = next(i for i,c in enumerate(s1[start:],start) if not c.isdigit())
result = s1[end:end+int(s1[start:end])]
print(result)
ABCDERTYUIOP
If you want to use the re module, you only need the first occurrence of a number, so use re.search() instead of re.findall():
import re
m = re.search(r"\d+",s1)
result = s1[m.end():m.end()+int(m.group())]
print(result)
ABCDERTYUIOP

string concatenation in a loop happens to be on the left . Why? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 2 years ago.
Improve this question
String concatenation happens to be on the right side, example:
foo = 'Sorting1234'
foo += 'er'
print(foo)
Sorting1234er
But in a loop this happens:
string = 'Sorting1234'
x = ''
for c in string:
if c.islower():
x+=c
if c.isupper():
x+=c
print(x)
Sorting
I would expect the output to be:
ortingS
Since I am 'appending' the lowercase first in the loop and 'appending' the uppercase later.
At the moment, you are processing the letters in the order of the original string, rather than by case. This means that your current for loop has little effect but to prevent the printing of numeric values.
One way to achieve the behaviour you're looking for, with the lower case characters appended first, would be to use two loops: the first looking for lower case characters and the second looking for upper case characters, i.e.:
string = 'Sorting1234'
x = ''
for c in string:
if c.islower():
x += c
for c in string:
if c.isupper():
x += c
print(x)
Output:
ortingS
An alternative way, requiring one pass over the string, could be to store lists of the lower and upper case characters, then join them at the end:
lower, upper = [], []
for c in string:
if c.islower():
lower.append(c)
elif c.isupper():
upper.append(c)
print(''.join(lower + upper))
Output:
ortingS
string = 'Sorting1234'
x = ''
for c in string:
if c.islower():
x+=c
if c.isupper():
x+=c
print(x)
print(x)
x=''
#x += c -> x = x + x -> appends c to the right of x, which it's doing it correctly
When printing the output you can see:
S
So
Sor
Sort
Sorti
Sortin
Sorting
You can see you are simply looping through the string and appending each letter, the if statements are practically useless in your case.

Addition binary numbers [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I need a help of my code, i have make addition of passing two variable of two binary numbers and the answer is incorrect!
in my code
import data as s
s.num
s.demo
def add_binary_nums(x,y):
max_len = max(len(x), len(y))
x = x.zfill(max_len)
y = y.zfill(max_len)
result = ''
carry = 0
for i in range(max_len-1, -1, -1):
r = carry
r += 1 if x[i] == '1' else 0
r += 1 if y[i] == '1' else 0
result = ('1' if r % 2 == 1 else '0') + result
carry = 0 if r < 2 else 1
if carry !=0 : result = '1' + result
return result.zfill(max_len)
print("start here")
demoo = (add_binary_nums(s.num,s.demo))
print(demoo)
assume the values as num="011000100110111101100010" and demo="001" and the answer of above code is 011000100110111101100110 , and it's wrong answer! when i pass the value like
num="011000100110111101100010"
demo="001"
i got the the answer 01111011000010110011101010 .
and fpr passing the value like
print(add_binary_nums('001', '001'))
the result will be 01100010011011110110010 i'm getting 3 different results!!
Any suggestion!
space not effect, i remove the space and the answer is same wrong
I tried your script and found out you have an extra space on the right side of your value variable. If you remove it, it should work (returns 010). I would recommend to trim your input values before proceeding with the algorithm.
value = value.strip()
If you just interested in the result but not in implementation (May be you are trying to learn something new or it is an assignment), you can first convert the binary numbers to int and add them and again convert back to binary string.
See this code:
value = '001 '
demo = '001'
def add_binary_nums(x,y):
x_int = int(x, 2)
y_int = int(y, 2)
result = x_int + y_int
return '{0:08b}'.format(result)
print(add_binary_nums(value, demo))
Output:
00000010
To understand '{0:08b}'.format(result), visit this link.
EDIT:
thx, for sure i care about the implementation, its not assignemt or homework to convert numbers into binary, and the code above its peace of my program, im passing many variables have binary number i give u one example , when i pass variable from other python code, assume , n="011000100110111101100010" and m="0001", when i run the code , its shows wrong answer!, remember i'm pass variable and i got result 011000100110111101100110 !
Try the code below. I am getting the right results with python3.
value = '011000100110111101100010'
demo = '0001'
def add_binary_nums(x,y):
x=x.strip()
y=y.strip()
max_len = max(len(x), len(y))
print("Max: %d X: %s Y %s" %(max_len, x, y))
x = x.zfill(max_len)
y = y.zfill(max_len)
result = ''
carry = 0
print("X: %s Y: %s" % (x, y))
for i in range(max_len-1, -1, -1):
print(i)
r = carry
r += 1 if x[i] == '1' else 0
r += 1 if y[i] == '1' else 0
result = ('1' if r % 2 == 1 else '0') + result
carry = 0 if r < 2 else 1
if carry !=0 : result = '1' + result
return result.zfill(max_len)
demoo = (add_binary_nums(demo, value))
print(demoo)
The problem only exists with the trailing space. When running the code with trailing space it produces the output 0011, when running the code without the trailing space produces the output 010
The reason this occurs is due to the space and how you use zfill. If we look at the data when there is a trailing space on one of them.
if we assume x="001" and y='001 ' then max_len will be set as 4 since y has 4 chars in it. you then do zfill on x and zfill on y. this will pad x with an extra leading 0 to make it 4 chars. It will have no effect on y since its already 4 chars. So you will end up with
x="0001"
y="001 "
As you can see these are now not in the same representation. So when you start to do your calculations your first iteration on index 3 will be comparing the "1" from x and the space char from y. You code says if its not a 1 then its a 0. since space isnt a 1 then you default it to a 0.
So your essentially treating it like
x="0001"
y="0010"
and the result of that would indeed correctly be "0011"
So the issue is 100% with your space in the string. I would suggest either validate your input to the function to be sure it contains only 1s or 0s if it doesnt raise a ValueError. Or at a minimum call strip method of string to remove any leading or trailing spaces from the string.
Look at how you initialized your variables (empty space, quotes). Seems off to me for a binary representation...
value = '001 '
demo = "001"
Just use python binary literals: How do you express binary literals in Python?
Rewrite print(add_binary_nums(value, demo)) as print(bin(int(value, 2), int(demo, 2)))
running your code leaves me with the result 0011 not as you mentioned 001001. Leaving out the space in the first "value" variable leaves me with the result 010.
Hope this helps!
Edit: I also would suggest to just add the numbers in int-mode and then convert the int back to binary if you insist in having the space and the input as you have.

How to place random dots in string? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I have code
import random
lst = ['.']
string = 'o3oyrwrj0jtirvwp5sh57oed67d5zy'
print ''.join('%s%s' % (x, random.choice(lst) if random.random() > 0.5 else '') for x in string)
It generates string with random dots between symbols:
o3.oy.r.wrj.0jt.i.rv.w.p5sh57.oe.d6.7.d.5z.y
o3oyr.wr.j.0.j.ti.rvw.p5sh5.7o.e.d6.7.d5zy
o.3o.y.rw.r.j.0.jt.i.r.v.wp.5sh.5.7.oe.d6.7.d5.zy
I need to generate string with number of dots from 1 to 10, and except results
dot at the end 'o.3.oyrwrj.0.jt.irv.wp.5.s.h57oe.d.67.d.5.zy.'
dot in the begin 'o.3.oyrwrj.0.jt.irv.wp.5.s.h57oe.d.67.d.5.zy'
double+ dot 'o..3.oyrwrj.0.jt.irv.wp.5.s.h57oe.d.67.d.5.zy'
I need only from 1 up to 10dots (not 10+)
You can use random.sample to select a random set of indices at which you will insert a dot instead of drawing at each index.
Forming slices out of these indices and joining with '.'.join will prevent pairs of dots as well as heading and trailing dots if you exclude first and last indices.
from random import sample
def insert_dots(s, k):
indices = sorted(sample(range(1, len(s) - 1), k))
intervals = []
for i, j in zip([0] + indices, indices + [len(s)]):
intervals.append(s[i:j])
return '.'.join(intervals)
Example
s = 'foobar'
for _ in range(5):
print (insert_dots(s, 3))
Output
fo.o.ba.r
fo.ob.a.r
f.oob.a.r
fo.o.b.ar
fo.o.ba.r
If you need a random number of dots, you can then do this.
insert_dots(s, randint(1, 10))
You can use this if statement:
if string.startswith('.')
# Raise dot at the beginning exception
elif string.endswith('.'):
# Raise dot at the end exception
elif '..' in string:
# Raise double dot exception

Creating my own string functions [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
def tlower(str1):
list = list(str1)
final = ''
for char in range(0,len(str1)):
if list[char] in UPPERCASE:
for ascii in range(0,len(UPPERCASE)):
if list[char] == UPPERCASE[ascii]:
list[char] = LOWERCASE[ascii]
final += list[char]
return final
NOTE - UPPERCASE and LOWERCASE are strings of all upper/lowercase letters
NOTE - can NOT use any string functions built into python (Replace, etc..)
I have this function to turn any string into all lower case, (Yes i know there is a built in function..) But compared to my other string functions I have created, this is fairly long, any better approach I should take to do doing this?
UPPERCASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
LOWERCASE = "abcdefghijklmnopqrstuvwxyz"
def to_lower(s, trans=dict(zip(UPPERCASE, LOWERCASE))):
return ''.join(trans.get(ch,ch) for ch in s)
print to_lower('This Is a TEST') # => 'this is a test'
Edit:
zip() takes two lists and returns pairs of values, ie
zip('ABC', 'abc') # => [('A','a'), ('B','b'), ('C','c')]
dict() makes a dictionary - in this case,
{'A':'a', 'B':'b', 'C':'c'}
trans.get(x, y) is a more compact way of saying as trans[x] if x in trans else y. In this case, "if you have a lowercase version of this letter, return it, otherwise give back the original letter".
and if you don't like .join, how about reduce?
from operator import add
def to_lower(s, trans=dict(zip(UPPERCASE, LOWERCASE))):
return reduce(add, (trans.get(ch,ch) for ch in s), '')
For completeness:
def to_lower(string):
ords = (ord(c) for c in string)
return ''.join(chr(o + 32 * (65 <= o <= 90)) for o in ords)

Categories