I want to write a function "longest" where my input doc test looks like this (python)
"""
>>>longest('1211')
1
>>>longest('1212')
2
>>>longest('212111212112112121222222212212112121')
2
>>>lvs('1')
0
>>>lvs('121')
0
>>>lvs('12112')
0
"""
What I am trying to achieve is that for example in the first case the 1 is repeated in the back with "11" so the repeated part is 1 and this repeated part is 1 character long it is this length that this function should return.
So in the case of the second you got "1212" so the repeated part is "12" which is 2 characters long.
The tricky thing here is that the longest is "2222222" but this doesn't matter since it is not in the front nor the back. The solution for the last doc test is that 21 is being repeated which is 2 characters long.
The code I have created this far is following
import re
def repetitions(s):
r = re.compile(r"(.+?)\1+")
for match in r.finditer(s):
yield (match.group(1), len(match.group(0)) / len(match.group(1)))
def longest(s):
"""
>>> longest('1211')
1
"""
nummer_hoeveel_keer = dict(repetitions(s)) #gives a dictionary with as key the number (for doctest 1 this be 1) and as value the length of the key
if nummer_hoeveel_keer == {}: #if there are no repetitive nothing should be returnd
return 0
sleutels = nummer_hoeveel_keer.keys() #here i collect the keys to see which has has the longest length
lengtes = {}
for sleutel in sleutels:
lengte = len(sleutel)
lengtes[lengte] = sleutel
while lengtes != {}: #as long there isn't a match and the list isn't empty i keep looking for the longest repetitive which is or in the beginning or in the back
maximum_lengte = max(lengtes.keys())
lengte_sleutel = {v: k for k, v in lengtes.items()}
x= int(nummer_hoeveel_keer[(lengtes[maximum_lengte])])
achter = s[len(s) - maximum_lengte*x:]
voor = s[:maximum_lengte*x]
combinatie = lengtes[maximum_lengte]*x
if achter == combinatie or voor == combinatie:
return maximum_lengte
del lengtes[str(maximum_lengte)]
return 0
when following doc test is put in this code
"""
longest('12112')
0
""
there is a key error where I put "del lengtes[str(maximum_lengte)]"
after a suggestion of #theausome I used his code as a base to work further with (see answer): this makes my code right now look like this:
def longest(s):
if len(s) == 1:
return 0
longest_patt = []
k = s[-1]
longest_patt.append(k)
for c in s[-2::-1]:
if c != k:
longest_patt.append(c)
else:
break
rev_l = list(reversed(longest_patt))
character = ''.join(rev_l)
length = len(rev_l)
s = s.replace(' ','')[:-length]
if s[-length:] == character:
return len(longest_patt)
else:
return 0
l = longest(s)
print l
Still there are some doc tests that are troubling me like for example:
>>>longest('211211222212121111111')
3 #I get 1
>>>longest('2111222122222221211221222112211')
4 #I get 1
>>>longest('122211222221221112111')
4 #I get 1
>>>longest('121212222112222112')
6 #I get 1
Anyone has ideas how to deal with/ approach this problem, maybe find a more graceful way around the problem ?
Try the below code. It works perfectly for your input doc tests.
def longest(s):
if len(s) == 1:
return 0
longest_patt = []
k = s[-1]
longest_patt.append(k)
for c in s[-2::-1]:
if c != k:
longest_patt.append(c)
else:
break
rev_l = list(reversed(longest_patt))
character = ''.join(rev_l)
length = len(rev_l)
s = s.replace(' ','')[:-length]
if s[-length:] == character:
return len(longest_patt)
else:
return 0
l = longest(s)
print l
Output:
longest('1211')
1
longest('1212')
2
longest('212111212112112121222222212212112121')
2
longest('1')
0
longest('121')
0
longest('12112')
0
Related
Can someone help me to solve the python program in the link below
<https://hr.gs/70xk >
Given a string S of length N that is indexed from 0 to N-1, print its even-indexed and odd-indexed characters as 2 space-separated strings on a single line.
my code to solve the problem is below
def fun(x):
fe = ''
fo = ''
if len(x) == 1:
pass
else :
val = list(x)
for i in val :
if val.index(i) % 2 == 0:
fe = fe + i
else :
fo = fo + i
print(fe,fo)
for stdin in range(3):
inputs = input("")
fun(inputs)
but this has solved only one case where the input are
2
Hacker
Rank
but for the input below
2
ivvkxq
ivvkx
the output I got was
ix vvkq
ix vvk
but the expected output was
ivx vkq
ivx vk
Something like this. It uses what ack mentioned. enumerate() gives you the index and value to separate variables.
def fun(x):
fe = ''
fo = ''
val = list(x)
for index, value in enumerate(val):
if index % 2 == 0:
fe = fe + value
else :
fo = fo + value
print(fe,fo)
for stdin in range(3):
inputs = input("")
fun(inputs)
Another approach using SLICING:
def fun(x):
print(x[::2],x[1::2])
# evens odds
fun('ivvkxq') # ivx vkq
fun('ivvkx') # ivx vk
So I am trying to make something that subtracts a certain amount from a string to make the 2 strings equal in length the problem is when I try to find the length of the element 1 which is stored as 0000 0000 it returns 1. Also, the code is grabbing from a file but the only relevant element is 1. Here is the code in question:
import re
insSpec2 = {}
z = 0
bool(z)
TestString = "0100 0001"
while z == 0:
f = open("Specifier", 'r')
for word in f:
i = 0
insSpec2[i] = re.split('r|a', word)
print(insSpec2[i])
insLength = len(insSpec2[i])
testLength = len(TestString)
if testLength > insLength:
diff = testLength-insLength
else:
diff = insLength-testLength
print(insLength)#returns 1
print(testLength, insLength) #returns 9 1
print(diff)#returns 8
print(insSpec2[0].__len__()) #returns 1
if insLength < testLength:
changeVar = 8 - insLength
while TestString != insSpec2:
#print(testLength)
newStr = TestString[:-diff]
#print(newStr)
elif insSpec2[i] == TestString:
print("Found Match", insSpec2[i])
z = 1
break
i += 1
That is because re.split returns a list not a string, insSpec[i] = ['0000 0000']. It has length 1
I don't know why, but I am getting value of scope as final as 0 even len(s) as zero in the last line of countfrequency(s) function.
import collections
def countfrequency(s):
final = 0
flag = 1
d = dict(collections.Counter(s))
for item in d:
if d[item] <= k:
flag = 0
if flag == 1: #Here
final = max(final, len(s))
print(final)
s = "ababbc"
k = 2
for x in range(len(s)):
for y in range(1, len(s)):
countfrequency(s[x:y + 1])
It is because of 2 reasons :
Value of flag is 0 at last so it wont change the value of final
Length function takes object as a parameter and when unchanged it gives 0
So you can can either make flag 1 so that control goes inside if condition or print the value of len(s) out side the if condition
In addition to the answer posted by shaktiraj jadeja, the modified code is as follows:
import collections
def countfrequency(s, k):
final = 0
flag = 0
d = dict(collections.Counter(s))
# print(d)
for item in d:
if d[item] > k:
flag = 1
break
if flag == 1: #Here
# print("Inside:", final, len(s))
final = max(final, len(s))
print(final)
s = "ababbc"
k = 2
for x in range(len(s)):
for y in range(1, len(s)):
# print(s[x:y])
countfrequency(s[x:y + 1], k)
To start with there is no problem of scope.
Now lets get back to the problem
Lets define a rule.
Rule: If a sub string has each character repeated more than k(=2) times in it. Then it is a good substring. Else it is a bad substring
Then your code simply prints the length of good sub string or 0 in case of bad substring
In short in your example string s= "ababbc" contains no good substring
if you try S = "aaaaaa" you will see many numbers printed other than 0 (exactly 11 0's and 10 other numbers)
Now either this was your confusion or you wrote the wrong code for some logic
I hope this helps
I am trying to generate combination of ID's
Input: cid = SPARK
oupout: list of all the comibnations as below, position of each element should be constant. I am a beginner in python any help here is much appreciated.
'S****'
'S***K'
'S**R*'
'S**RK'
'S*A**'
'S*A*K'
'S*AR*'
'S*ARK'
'SP***'
'SP**K'
'SP*R*'
'SP*RK'
'SPA**'
'SPA*K'
'SPAR*'
'SPARK'
I tried below, I need a dynamic code:
cid = 'SPARK'
# print(cid.replace(cid[1],'*'))
# cu_len = lenth of cid [SPARK] here which is 5
# com_stars = how many stars i.e '*' or '**'
def cubiod_combo_gen(cu_len, com_stars, j_ite, i_ite):
cubiodList = []
crange = cu_len
i = i_ite #2 #3
j = j_ite #1
# com_stars = ['*','**','***','****']
while( i <= crange):
# print(j,i)
if len(com_stars) == 1:
x = len(com_stars)
n_cid = cid.replace(cid[j:i],com_stars)
i += x
j += x
cubiodList.append(n_cid)
elif len(com_stars) == 2:
x = len(com_stars)
n_cid = cid.replace(cid[j:i],com_stars)
i += x
j += x
cubiodList.append(n_cid)
elif len(com_stars) == 3:
x = len(com_stars)
n_cid = cid.replace(cid[j:i],com_stars)
i += x
j += x
cubiodList.append(n_cid)
return cubiodList
#print(i)
#print(n_cid)
# for item in cubiodList:
# print(item)
print(cubiod_combo_gen(5,'*',1,2))
print(cubiod_combo_gen(5,'**',1,3))
For every character in your given string, you can represent it as a binary string, using a 1 for a character that stays the same and a 0 for a character to replace with an asterisk.
def cubiod_combo_gen(string, count_star):
str_list = [char0 for char0 in string] # a list with the characters of the string
itercount = 2 ** (len(str_list)) # 2 to the power of the length of the input string
results = []
for config in range(itercount):
# return a string of i in binary representation
binary_repr = bin(config)[2:]
while len(binary_repr) < len(str_list):
binary_repr = '0' + binary_repr # add padding
# construct a list with asterisks
i = -1
result_list = str_list.copy() # soft copy, this made me spend like 10 minutes debugging lol
for char in binary_repr:
i += 1
if char == '0':
result_list[i] = '*'
if char == '1':
result_list[i] = str_list[i]
# now we have a possible string value
if result_list.count('*') == count_star:
# convert back to string and add to list of accepted strings
result = ''
for i in result_list:
result = result + i
results.append(result)
return results
# this function returns the value, so you have to use `print(cubiod_combo_gen(args))`
# comment this stuff out if you don't want an interactive user prompt
string = input('Enter a string : ')
count_star = input('Enter number of stars : ')
print(cubiod_combo_gen(string, int(count_star)))
It iterates through 16 characters in about 4 seconds and 18 characters in about 17 seconds. Also you made a typo on "cuboid" but I left the original spelling
Enter a string : DPSCT
Enter number of stars : 2
['**SCT', '*P*CT', '*PS*T', '*PSC*', 'D**CT', 'D*S*T', 'D*SC*', 'DP**T', 'DP*C*', 'DPS**']
As a side effect of this binary counting, the list is ordered by the asterisks, where the earliest asterisk takes precedence, with next earliest asterisks breaking ties.
If you want a cumulative count like 1, 4, 5, and 6 asterisks from for example "ABCDEFG", you can use something like
star_counts = (1, 4, 5, 6)
string = 'ABCDEFG'
for i in star_counts:
print(cubiod_combo_gen(string, star_counts))
If you want the nice formatting you have in your answer, try adding this block at the end of your code:
def formatted_cuboid(string, count_star):
values = cubiod_combo_gen(string, count_star)
for i in values:
print(values[i])
I honestly do not know what your j_ite and i_ite are, but it seems like they have no use so this should work. If you still want to pass these arguments, change the first line to def cubiod_combo_gen(string, count_star, *args, **kwargs):
I am not sure what com_stars does, but to produce your sample output, the following code does.
def cuboid_combo(cid):
fill_len = len(cid)-1
items = []
for i in range(2 ** fill_len):
binary = f'{i:0{fill_len}b}'
#print(binary, 'binary', 'num', i)
s = cid[0]
for idx, bit in enumerate(binary,start=1):
if bit == '0':
s += '*'
else: # 'bit' == 1
s += cid[idx]
items.append(s)
return items
#cid = 'ABCDEFGHI'
cid = 'DPSCT'
result = cuboid_combo(cid)
for item in result:
print(item)
Prints:
D****
D***T
D**C*
D**CT
D*S**
D*S*T
D*SC*
D*SCT
DP***
DP**T
DP*C*
DP*CT
DPS**
DPS*T
DPSC*
DPSCT
I have really been struggling to solve this problem. This is the problem:
Given a string describing the circuit, calculate the total resistance
of the circuit.
Here is an example:
input: 3 5 S
expected output: 8
The operands in the string are trailed by the operator, denoting if the resistors are either in Series or Parallel. However let's analyze a more complicated circuit:
input: 3 5 S 0 P 3 2 S P
expected output: 0
Step by step:
The 3 5 S at the beginning of the input gives us 8 and hence the first intermediate step is the string 8 0 P 3 2 S P.
8 0 P gives us 0, as one resistor is short-circuited and consequently we get 0 3 2 S P.
3 2 P is 5.
and finally 0 5 P is 0.
Here is my attempt. I tried using recursion as it seemed like a problem that can be solved that way. Firstly I wrote a helper function:
def new_resistance(a,b,c):
if c == '':
if int(a) == 0 or int(b) == 0:
return 0
else:
return 1/(1/int(a) + 1/int(b))
else:
return int(a) + int(b)
And the function that calculates the newn resistance of the circuit:
def resistance(array):
if isinstance(array, int):
return array
else:
if isinstance(array,list):
temp = array
else:
temp = array.split(" ")
i = 0
while True:
try:
a = new_resistance(temp[i], temp[i+1], temp[i+2])
except Exception as e:
i += 1
if len(temp[i+3:]) == 0:
return resistance(new_resistance(temp[i], temp[i+1], temp[i+2]))
else:
return resistance(temp[:i] + [new_resistance(temp[i], temp[i+1], temp[i+2])] + temp[i+3:])
The idea behind the program is to start at the beginning of the list and calculate the resistance of the first three elements of the list, then to append them at the beginning of a new list (without the three elements) and call the function again with the new list. Do this until only a single integer remains and return the integers.
Any help is appreciated.
UPDATE:
The solution to the problem, using a stack and a parser similar to a NPR parser.
operator_list = set('PS')
def resistance(circuit):
temp = circuit.split(" ")
stack = []
for char in temp:
if char in operator_list:
a = new_resistance(stack.pop(), stack.pop(), char)
print(a)
stack.append(a)
else:
print(char)
stack.append(char)
return stack[-1]
def new_resistance(a,b,c):
if c == 'P':
if float(a) == 0 or float(b) == 0:
return 0
else:
return 1/(1/float(a) + 1/float(b))
else:
return float(a) + float(b)
circuit = '3 5 S 0 P 3 2 S P'
resistance(circuit)
# 3
# 5
# 8.0
# 0
# 0
# 3
# 2
# 5.0
# 0
The problem is that once you reach 0 3 2 S P, you cannot simply take the first 3 elements. You need to look for number number S_or_P, wherever it is in the string.
You can use a regex for this task:
import re
circuit = '3 5 S 0 P 3 2 S P'
pattern = re.compile('(\d+) +(\d+) +([SP])')
def parallel_or_serie(m):
a, b, sp = m.groups()
if sp == 'S':
return str(int(a) + int(b))
else:
if a == '0' or b == '0':
return '0'
else:
return str(1/(1/int(a) + 1/int(b)))
while True:
print(circuit)
tmp = circuit
circuit = re.sub(pattern, parallel_or_serie, circuit, count=1)
if tmp == circuit:
break
# 3 5 S 0 P 3 2 S P
# 8 0 P 3 2 S P
# 0 3 2 S P
# 0 5 P
# 0
Note that 1 1 P will output 0.5. You could replace int by float and modify the regex in order to parse floats.
Your program, or more specifically your parser, seems to be relying on the Reverse Polish Notation, which in turn is a small variant of the Normal Polish Notation. Simply put, the RPN is an abstract representation where the operators of an arithmetical expression follow their operands, unlike in the Normal Polish Notation where the operators precede their operands. Parsers based on this representation can be easily implemented by using stacks (and usually do not need to interpret parentheses).
If you are tasked with developing that parser you may get some input from the Wikipedia article I linked above.
Credits to #none who first recognized the RPN.
Old memories came to my mind. I was playing with the FORTH language on 8-bit computers in 1980s. OK, back to Python:
circuit = '3 5 S 0 P 3 2 S P'
stack = []
for n in circuit.split():
if n == 'S':
r1 = stack.pop()
r2 = stack.pop()
stack.append(r1+r2)
elif n == 'P':
r1 = stack.pop()
r2 = stack.pop()
stack.append(0.0 if (r1 == 0 or r2 == 0) else 1/(1/r1+1/r2))
else:
stack.append(float(n))
assert len(stack) == 1
print(stack[0])
On in the spirit of VPfB for any combination of serial parallel (not only in pairs)
def calculateresistor(dataString):
stack = []
r = []
cicuit=dataString
for n in circuit.split():
if n == 'S':
stackSize=size(stack)
if size(stack)>=2:
for k in range(0,size(stack)-1):
r.append(float(stack.pop()))
r.append(float(stack.pop()))
stack.append((r[-1]+r[-2]))
elif n == 'P':
stackSize=size(stack)
if size(stack)>=2:
for k in range(0,size(stack)-1):
r.append(float(stack.pop()))
r.append(float(stack.pop()))
r.append(0.0 if (r[-1] == 0 or r[-2] == 0) else (1/(1/r[-1]+1/r[-2])))
stack.append(r[-1])
else:
stack.append(float(n))
assert len(stack) == 1
return(stack)