Python - how to restore original string after replace? [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
Let's say, the original string is:
a = 'DA115792C339A5E674416AB0559BF5CB8D38E88B1E71F4DFAE896EBD2D13ABB13FFB1DC687DCF0C270A8BF4861D2E6D26E74DC81C18EB53FD5C52AA691A8F16BDA4E1EB8009B00DCD61457E34C438F23EF3D1FD905CF689793CC1E02E1ECB6778A1E2720D416AC432959A8A3B20B43525A856C97E4D404065D1D30ADC74D012B27D00B0029AD3940CB2C9F2AB6C01D430F3A58584C5DB6C98839579AF2A8F90A5D80B5097D547105DF2D9F9485E9F2CCFD6F9ECDDBD562FE09EA81C19B18482BD483AEBAB8481EE208887909DDAE826629538F36E6A50CEECBF3462E9FFBDAC6363F3A9A56F31081EBF28AD0FCF288B0DB8CB44735B9D7E6D193D55C90767E83'
Now, all the instances of 'D6' were replaced with '9F' in above string by doing:
b = a.replace('D6','9F')
b = 'DA115792C339A5E674416AB0559BF5CB8D38E88B1E71F4DFAE896EBD2D13ABB13FFB1DC687DCF0C270A8BF4861D2E6D26E74DC81C18EB53FD5C52AA691A8F16BDA4E1EB8009B00DC9F1457E34C438F23EF3D1FD905CF689793CC1E02E1ECB6778A1E2720D416AC432959A8A3B20B43525A856C97E4D404065D1D30ADC74D012B27D00B0029AD3940CB2C9F2AB6C01D430F3A58584C5DB6C98839579AF2A8F90A5D80B5097D547105DF2D9F9485E9F2CCF9FF9ECDDBD562FE09EA81C19B18482BD483AEBAB8481EE208887909DDAE826629538F36E6A50CEECBF3462E9FFBDAC6363F3A9A56F31081EBF28AD0FCF288B0DB8CB44735B9D7E6D193D55C90767E83'
Now, let's say, we only have the value of b and not a. We need to perform some operations on b to retrieve the original value of a.
Also, we know that the value of 'a' should satisfy a certain mathematical condition.
The mathematical condition is:
number z should be divisible by a (z % a == 0)
z = 55057004365075793824891923502198296150348187500859129529014955509148421282041969078213265169463529503768779794209446773790749529176461595867792548236095966024387560672845152234957439383409540755826755640123124159246487058454615922008741879614211920551517049373314503998980825185719370304183623398662036133862488876163410866971729000216470924616148028986990798495248878127793311548452974671645100371499570058070179424193067736979204502413302335974105838586819414807952974885796840178274113497125765593996690493177955553456655538977929256055738007112424150644005452979891672942537126552535517394691741201589304958975238
We need to leverage this mathematical property of 'a' to restore it from b.
I understand that we cannot use the replace() function on b to get back 'a' because some of the original instances of '9F' might get replaced.
I think we need to perform replace operation in different positions till we satisfy that condition.
For the given string we have:
b.count('9F')
6
So, we would have to replace '9F' with 'D6' in different combinations of positions till we get back 'a' satisfying the mathematical condition, 'C'.
I did something like:
count = b.count('9F')
for i in range(1,count+1):
print "trying: %d" %(i)
tmp = b.replace('9F','D6',i)
num = int(tmp, 16)
if z % num == True:
print num
This seems to be a problem related to permutations and combinations.

You already have 4 instances of 9F in your original string. Those are causing the wierd behaviour
a = 'DA115792C339A5E674416AB0559BF5CB8D38E88B1E71F4DFAE896EBD2D13ABB13FFB1DC687DCF0C270A8BF4861D2E6D26E74DC81C18EB53FD5C52AA691A8F16BDA4E1EB8009B00DCD61457E34C438F23EF3D1FD905CF689793CC1E02E1ECB6778A1E2720D416AC432959A8A3B20B43525A856C97E4D404065D1D30ADC74D012B27D00B0029AD3940CB2C9F2AB6C01D430F3A58584C5DB6C98839579AF2A8F90A5D80B5097D547105DF2D9F9485E9F2CCFD6F9ECDDBD562FE09EA81C19B18482BD483AEBAB8481EE208887909DDAE826629538F36E6A50CEECBF3462E9FFBDAC6363F3A9A56F31081EBF28AD0FCF288B0DB8CB44735B9D7E6D193D55C90767E83'
print(a.count('9F'))
#4
Otherwise the string.replace works perfectly
a = 'hello'
b = a.replace('l','a')
print(b)
#heaao
c = b.replace('a','l')
print(c)
#hello
print( a == c)
#True
Gives you True (Convert l to a, and then a to l)
Possible solution, replace existing 9F to something not present in the string,say XY, then use it in replacing back as well
a = 'DA115792C339A5E674416AB0559BF5CB8D38E88B1E71F4DFAE896EBD2D13ABB13FFB1DC687DCF0C270A8BF4861D2E6D26E74DC81C18EB53FD5C52AA691A8F16BDA4E1EB8009B00DCD61457E34C438F23EF3D1FD905CF689793CC1E02E1ECB6778A1E2720D416AC432959A8A3B20B43525A856C97E4D404065D1D30ADC74D012B27D00B0029AD3940CB2C9F2AB6C01D430F3A58584C5DB6C98839579AF2A8F90A5D80B5097D547105DF2D9F9485E9F2CCFD6F9ECDDBD562FE09EA81C19B18482BD483AEBAB8481EE208887909DDAE826629538F36E6A50CEECBF3462E9FFBDAC6363F3A9A56F31081EBF28AD0FCF288B0DB8CB44735B9D7E6D193D55C90767E83'
#Replace 9F to XY, then D6 to 9F
b = a.replace('9F','XY').replace('D6','9F')
#Replace 9F to D6, then XY to 9F
c = b.replace('9F', 'D6').replace('XY', '9F')
print(a == c)
#True

You won't retrieve your original string back after these two operations, because you probably have "9F" in your original string, too:
test = "D69F"
changed = test.replace("D6", "9F")
print(changed)
# 9F9F
undo_change = changed.replace("9F", "D6")
print(undo_change)
# D6D6
If it don't interfere with your intermediate step you can mask your replacement, e.g. with test.replace("D6", "§9F").

Related

Most pythonic way to split string into integers [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 21 days ago.
Improve this question
I have a string that needs to be validated that it is of the form of ‘#-#’ where the #s should be unsigned integers. What is the most pythonic way to split this into two integers, lo and hi, possibly including type-checking/validation that lo < hi, unsigned ints, and so on?
I’ve thought about various solutions, but I have varying criteria and it must make sure that # and # are unsigned ints with only the one hyphen in between.
I'm not sure if this is absolutely the most pythong way, but I'd split on the - character and use a list comprehension to generate lo and hi:
[lo, hi] = [int(x) for x in s.split('-')]
You can try something like this:
string = "43-3" #example data
num = string.split("-") #split the string
lo = int(num[0])
hi = int(num[1])
if(lo<hi):
print("ok")
else:
print("ko")
this will work as long your string is exactly as you told us and there are only unsigned ints in the string.
Best I can think of is using a regular expression to match the exact pattern and assert that everything is correct. Note however that doing it this way will crash the program as soon as an invalid input appears, unless you do some extra error handling.
import re
input_strings = [
"123-321",
"92646-278364",
# "12345-123", # error: low > high
# "123.45-98765", # error: not integers
]
def get_num_pair(num_str: str):
m = re.match(r'(\d+)-(\d+)', num_str)
assert m and len(m.groups()) == 2
lo, hi = int(m.group(1)), int(m.group(2))
assert 0 <= lo <= hi
return lo, hi
for input_str in input_strings:
print(get_num_pair(input_str))
Expanding on Mureinik's answer - I'd suggest you do the following:
use a list comprehension to split the list on '-' and turn each bit into ints
carry out validation on the resulting list to ensure it meets your requirements - exactly two elements and the first one is lower
wrap this in a try, except block in case the list comprehension gives an error
wrap that in a function that encapsulates the concept of splitting #-# strings
e.g.
def parse_twoval_str(twoval_str):
try:
vals = [int(s) for s in twoval_str.split("-")]
except ValueError:
raise ValueError("Could not parse input - must be of form '123-234'")
if len(vals) != 2:
raise ValueError("Input must contain two values")
a, b = vals
if a > b:
raise ValueError("First value must be less than second value")
return a, b

Python: insert 68 empty strings into a list [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 2 years ago.
Improve this question
I am extracting values from excel into a list but some of them are blank.
I want to check if the list is empty, and if empty insert 68 empty strings. Is there a way to do that?
a = []
if not a:
#enter 68 empty strings into a. eg: a = ['', '', '',....]
Python lets you multiply a list with a number to repeat it:
a = [''] * 68
If you also have other references to this list, so you actually need to update the same list instead of creating an new one, use extend:
a.extend([''] * 68)
Using the logical or operator, you can avoid conditions to create the list with empty strings, or keep the original list in case it was not empty:
a = a or [''] * 68
If a is empty, then it's falsey so the or will return the second argument.
If a is not empty, it is truthy so the or will return it.
a = []
if not a:
a.extend(["" for _ in range(68)])
Suppose you have a list a, and we want to insert n=68 blank strings at position i
a = [1, 2]
i = 1
n = 68
result = a[:i] + [''] * n + a[i:]
Then of course you can set a = result if you wanted to modify a directly. This is of course overkill, as you don't really want to insert into an existing list, this time, but I thought I'd answer the question asked.

How to call comparison operators from list [closed]

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 4 years ago.
Improve this question
Hi I want to install some kind of adjustable comparer where an element from a list a is compared to an element of a list Values with an operator which is read from a list Operators
a = [1,2,3,4] # This should be variable
Val = [0.5,1,10,7] # This should have the same length as a
Op = ['<','>','<>','<']
for i in range(len(a)):
print(a[i]Op[i]Val[i])
Instead of comparison symbols, use the function from operators.
May be this can help!
from operator import lt, gt, ne, le,eq
a = [1,2,3,4] # This should be variable
val = [0.5,1,10,7] # This should have the same length as a
operation = {'<': lt, '>': gt, '<>': ne, '=': eq}
op = ['<','>','<>','<']
for i,o,j in zip(a,op,val):
print(operation[o](i,j))
False
True
True
True
Using eval even in some situation it is unstable, but if only consider your case , it work as expected and better solution is sympy
a = [1,2,3,4] # This should be variable
Val = [0.5,1,10,7] # This should have the same length as a
Op = ['<','>','!=','<']
for i in range(len(a)):
parse_expr(str(a[i])+Op[i]+str(Val[i]))# or change to eval(str(a[i])+Op[i]+str(Val[i]))
False
True
True
True
Seems that you need programmatic way to call comparison operators, operator module will do the work. Either construct list of operator functions or make signs to operator mapping via dict
a = [1,2,3,4] # This should be variable
b = [0.5,1,10,7] # This should have the same length as a
c = ['<','>','<>','<']
use
for i in range(len(a)):
eval(str(a[i])+b[i]+str(c[i]))

Can this kind of code (if ... for if ... for ...) be both short and fast [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 5 years ago.
Improve this question
I have some problems with the following kind of code:
if a == b:
forloop:
CODE_1
k = t # t will be changed in CODE_1 and CODE_2
CODE_2
elif a == c:
forloop:
CODE_1
k = t + 1
CODE_2
As you can see, both the code in two for loop is very similar (they might just have some difference in several characters. The above is just an example.) Now I want to make it shorter because they are nearly the same.
I know there is a way to make it shorter:
forloop:
CODE_1
if a == b:
k = t
elif a == c:
k = t + 1
CODE_2
But the point is for every loop, it will need to do the comparison. I think it should be slower than the former one. And in fact, because a, b and c will not be affected by the for loop, it does not need to compare them every loop. Could anybody tell me how to make it shorter without making it slower?
I am now using python.
Sorry for not providing a specific code because I am just curious about this general situation. If this can be optimized only in some specific code, it will be great if you can point it out.
And copying is not the way to solve it since they still have some difference (not just 1 maybe 25 positions).
If a == c, you could simply call t = t + 1 before the loop, and use the same code whatever a is.
If t itself changes during the loop, you could write k = t + dt, where dt has been set to 0 or 1 depending on the value of a.
This should work, because, as you mentioned in your question:
And in fact, because a, b and c will not be affected by the for loop
Finally, it might be possible to use a dict instead of elif statements.
Generalizing another answer, you can lift comparisons and other code out of the loop.
Say that a == c is really expensive--perhaps they are big matrixes. You could do something like
compare = a == c #store comparison
for ... :
if compare:
...
else: ...
You can also pull any operations and computations that are constant out of the loop.

Separating strings in CamelCase to individual strings [closed]

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 5 years ago.
Improve this question
The question is as follows:
"A string exists in CamelCase format. For example: "ThisIsACamelCaseString".
A procedure/function is required that will:
1) prompt for the original entry
2) separate each word of the string
3) store each word in a separate array/list element
4) fill unused array/list elements with a rogue string such as "(Empty)".
After processing the preceding example, the array contents will look like this:
This
Is
A
Camel
Case
String
(Empty)
(Empty)
(Empty)
(Empty)
You may assume that the original string will contain no more than 10 separate words. Write program code in Python for this design."
This is what I tried:
a = input("Enter: ")
lists = list(a)
len = len(a)
alpha = ["Empty"]*10
alpha[0] = lists[0]
for i in range(len):
for j in range(len):
if lists[j + 1].isupper():
break
alpha[i] = alpha[i] + lists[j + 1]
for i in range(10):
print(alpha[i])
How do I find suitable code?
This is one way to do it:
a = 'ThisIsACamelCaseString'
b = [i for i, e in enumerate(a) if e.isupper()] + [len(a)]
c = [a[x: y] for x, y in zip(b, b[1:])]
final = ['(Empty)']*10
for i, case in enumerate(c):
final[i] = case
Use regular expressions to split camel case How to do CamelCase split in python .
Or just iterate over the string in a loop.

Categories