Hemanth Ravavarapu
Hemanth Ravavarapu

Reputation: 291

Filling the missing values in the specified format - Python

I'm given a problem that explicitly asks me not to use numpy or pandas.

Problem:

Given a string with digits and '_'(missing value) symbols you have to replace the '_' symbols as explained

Ex 1: _, _, _, 24 ==> 24/4, 24/4, 24/4, 24/4 i.e we. have distributed the 24 equally to all 4 places 

Ex 2: 40, _, _, _, 60 ==> (60+40)/5,(60+40)/5,(60+40)/5,(60+40)/5,(60+40)/5 ==> 20, 20, 20, 20, 20 i.e. the sum of (60+40) is distributed qually to all 5 places

Ex 3: 80, _, _, _, _  ==> 80/5,80/5,80/5,80/5,80/5 ==> 16, 16, 16, 16, 16 i.e. the 80 is distributed qually to all 5 missing values that are right to it

Ex 4: _, _, 30, _, _, _, 50, _, _  
==> we will fill the missing values from left to right 
    a. first we will distribute the 30 to left two missing values (10, 10, 10, _, _, _, 50, _, _)
    b. now distribute the sum (10+50) missing values in between (10, 10, 12, 12, 12, 12, 12, _, _) 
    c. now we will distribute 12 to right side missing values (10, 10, 12, 12, 12, 12, 4, 4, 4)

for a given string with comma separated values, which will have both missing values numbers like ex: "_, _, x, _, _, " you need fill the missing values Q: your program reads a string like ex: ", _, x, _, _, _" and returns the filled sequence Ex:

Input1: "_,_,_,24"
Output1: 6,6,6,6

Input2: "40,_,_,_,60"
Output2: 20,20,20,20,20

Input3: "80,_,_,_,_"
Output3: 16,16,16,16,16

Input4: "_,_,30,_,_,_,50,_,_"
Output4: 10,10,12,12,12,12,4,4,4

I'm trying to split the string in a list using the split function. I'm then trying to check for blanks on the left and the count the number of such blanks and then once I encounter a non-blank, I'm dividing that number by the total count i.e (no.blanks encountered before the number and number itself) and spreading the values and replacing the blanks left the number

Then I'm checking for the blanks in between two number and then applying the same logic, after which doing the same for blanks on the right.

However, the code I shared below is throwing all sorts of errors, and I believe there are gaps in logic I shared above, therefore would appreciate insights on solving this issue

def blanks(S):

  a= S.split()
  count = 0
  middle_store = 0
  #left
  for i in range(len(a)):
    if(a[i]=='_'):
      count = count+1  #find number of blanks to the left of a number
    else:
      for j in range(0,i+1):
        #if there are n blanks to the left of the number speard the number equal over n+1 spaces
        a[j] = str((int(a[i])/(count+1)))
        middle_store= i
    break  

  #blanks in the middle
  denominator =0
  flag = 0
  for k in len(middle_store+1,len(a)):
    if(a[k] !='_'):
      denominator = (k+1-middle_store)
      flag=k
    break

  for p in len(middle_store,flag+1):
    a[p] = str((int(a[p])/denominator))

  #blanks at the right 
  for q in len(flag,len(a)):
    a[q] = str((int(a[q])/(len(a)-flag+1)))

S=  "_,_,30,_,_,_,50,_,_"
print(blanks(S))

Upvotes: 0

Views: 9255

Answers (7)

Sayed Azharuddin
Sayed Azharuddin

Reputation: 55

# write your python code here
# you can take the above example as sample input for your program to test
# it should work for any general input try not to hard code for only given input strings
#run your code in the function for each of the inputs mentioned above and make sure that you get the same results
def appendvalues(value,startIndex,endIndex,values_list):
  #values_list=[]
  for i in range(startIndex,endIndex):
    values_list[i]=value
    #.append(value)
  #return values_list

def calculate_missing_values(values_list):
  filled_values=[]
  filled_positions=[]
  for i in range(len(values_list)):
    if(values_list[i].isdigit()):
      if(len(filled_positions) ==0):      
        missingvalues= int(int(values_list[i]) / (i+1))
        appendvalues(missingvalues,0,i+1,values_list)
      else:
        missingvalues= int((int(filled_values[len(filled_values)-1])+int(values_list[i])) / ((i+1)-filled_positions[len(filled_positions)-1]))
        appendvalues(missingvalues,filled_positions[len(filled_positions)-1],i+1,values_list)
      filled_positions.append(i)
      filled_values.append(int(values_list[i]))
  if(len(values_list) != filled_positions[len(filled_positions)-1]):
    missingvalues= int(int(values_list[filled_positions[len(filled_positions)-1]])/(len(values_list)- filled_positions[len(filled_positions)-1]))
    appendvalues(missingvalues,filled_positions[len(filled_positions)-1],len(values_list),values_list)
  return values_list

# you can free to change all these codes/structure
def curve_smoothing(string):
    # your code
    values_list = string.split(',')
    filled_values=calculate_missing_values(values_list)
    return filled_values#list of values

S=  "_,_,30,_,_,_,50,_,_"
smoothed_values= curve_smoothing(S)
print(smoothed_values)

Upvotes: 0

Saran Koundinya
Saran Koundinya

Reputation: 1

"Check this its work for all the inputs"

def replace(s):

val=0
lst=s.split(",")

if lst[0].isdigit():
    for i in range(1,len(lst)):
        if lst[i].isdigit():
            value=(int(lst[0])+int(lst[i]))//((i+1))
            for j in range(0,i+1):
                lst[j]=value
            index=i
            break    
else:
    for i in range(len(s)):
        if lst[i].isdigit():
            for j in range(i+1):
                lst[j]=(int(lst[i]))//(i+1)
            index=i
            value=int(lst[i])
            break
for i in range(index+1,len(lst)):
    if lst[i].isdigit():
        temp=(value+int(lst[i]))//(i-index+1)
        for j in range(index,i+1):
            lst[j]=temp
        index=i
        value=int(lst[i])


try :
    for i in range(index+1,len(lst)):
        if not(lst[i].isdigit()):
            count=lst.count('_')
            break
    temp1=value//(count+1)
    for i in range(index,len(lst)):
        lst[i]=temp1
except UnboundLocalError as e:
    print (e)
return lst     

Upvotes: -1

Jay
Jay

Reputation: 1201

def replace(string):
lst=string.split(',')
if lst[0].strip().isdigit():
    index0=0
    while True:
        index1=index0
        value1=int(lst[index0].strip())
        index2=index1
        for i in range((index1+1),len(lst)):
            if lst[i].strip().isdigit():
                index2=i
                break
        value2=0
        if index2>index1:
            value2=int(lst[index2].strip())
        else:
            index2=len(lst)-1
        value=str(int((value1+value2)/((index2-index1)+1)))
        for i in range(index1,index2+1):
            lst[i]=value
        index0=index2

        if index0>=(len(lst)-1):
            break

else:
    index0=0
    while True:
        index1=index0
        value1=0
        if lst[index0].strip().isdigit():
            value1=int(lst[index0].strip())
        index2=index1
        for i in range((index1+1),len(lst)):
            if lst[i].strip().isdigit():
                index2=i
                break
        value2=0
        if index2>index1:
            value2=int(lst[index2].strip())
        else:
            index2=len(lst)-1
        value=str(int((value1+value2)/((index2-index1)+1)))
        for i in range(index1,index2+1):
            lst[i]=value
        index0=index2

        if index0>=(len(lst)-1):
            break

return lst   

string = "20,_,_,30, _, _,10,_,_,_,_,110"
replace(string)

Upvotes: 0

maahi
maahi

Reputation: 1

# _, _, 30, _, _, _, 50, _, _ 
def replace(string):
    lst=string.split(',')
    for i in range(len(lst)):
        if lst[i].isdigit():
            for j in range(i+1):
                lst[j]=int(lst[i])//(i+1)
            new_index=i
            new_value=int(lst[i])
            break
    for i in range(new_index+1,len(lst)):
        if lst[i].isdigit():
            temp=(new_value+int(lst[i]))//(i-new_index+1)
            for j in range(new_index,i+1):
                lst[j]=temp
            new_index=i
            new_value=int(lst[i])
    try:
        for i in range(new_index+1,len(lst)):
            if not(lst[i].isdigit()):
                count=lst.count('_')
                break
        temp1=new_value//(count+1)
        for i in range(new_index,len(lst)):
            lst[i]=temp1
    except:
        pass
    return lst        

Upvotes: 0

udai
udai

Reputation: 1

A code for the problem thrown in question may also be done in the following way, though the code is not optimized and simplified, it is written with a different perspective:

import re 
def curve_smoothing(S): 

    pattern = '\d+'
    ls_num=re.findall(pattern, S)   # list of numeral present in string
    pattern = '\d+'
    spaces = re.split(pattern, S)  # split string to seperate '_' spaces

    if len(spaces[0])==0 and len(ls_num)==1:
        Space_num=len(re.findall('_',  S))
        sums=int(ls_num[0])
        repl_int=round(sums/(Space_num+1))
        S=re.sub(r'(\d{2})(,_)', r'{}\2'.format(str(repl_int)) , S, 1)
        S=re.sub('_', str(repl_int),S, Space_num)
        return S

    elif len(spaces[0])==0 and len(ls_num)>1:
        for i in range(1,len(spaces)):
            if i==1:
                Space_num=len(re.findall('_',  spaces[i]))
                sums=int(ls_num[i-1])+int(ls_num[(i)])
                repl_int=round(sums/(Space_num+2))
                S=re.sub(str(ls_num[i-1]), str(repl_int),S)
                S=re.sub('_', str(repl_int),S, Space_num)
                S=re.sub(str(ls_num[i]), str(repl_int),S,1)
                ls_num[i]=repl_int
            elif i<len(ls_num):
                Space_num=len(re.findall('_',  spaces[i]))
                sums=int(ls_num[i-1])+int(ls_num[(i)])
                repl_int=round(sums/(Space_num+2))
                S=re.sub(r'(\d{2})(,_)', r'{}\2'.format(str(repl_int)) , S, 1)
                S=re.sub('_', str(repl_int),S, Space_num)
                S=re.sub(str(ls_num[i]), str(repl_int),S,1)
                ls_num[i]=repl_int
            elif len(spaces[-1])!=0:
                Space_num=len(re.findall('_',  spaces[i]))
                repl_int=round(ls_num[(i-1)]/(Space_num+1))
                S=re.sub(r'(\d{2})(,_)', r'{}\2'.format(str(repl_int)) , S, 1)
                S=re.sub('_', str(repl_int),S, Space_num)
        return S


    else:
        for i in range(len(spaces)):
            if i==0:
                Space_num=len(re.findall('_',  spaces[i]))
                sums=int(ls_num[(i)])
                repl_int=round(sums/(Space_num+1))
                S=re.sub(r'(\d{2})(,_)', r'{}\2'.format(str(repl_int)) , S, 1)
                S=re.sub('_', str(repl_int),S, Space_num)
                S=re.sub(str(ls_num[i]), str(repl_int),S, 1)
                ls_num[i]=repl_int
            elif i>=1 and i<len(ls_num):
                Space_num=len(re.findall('_',  spaces[i]))
                sums=int(ls_num[i-1])+int(ls_num[(i)])
                repl_int=round(sums/(Space_num+2))
                S=re.sub(r'(\d{2})(,_)', r'{}\2'.format(str(repl_int)) , S, 1)
                S=re.sub('_', str(repl_int),S, Space_num)
                S=re.sub(str(ls_num[i]), str(repl_int),S,1)
                ls_num[i]=repl_int
            elif len(spaces[-1])!=0:
                Space_num=len(re.findall('_',  spaces[i]))
                repl_int=round(ls_num[(i-1)]/(Space_num+1))
                S=re.sub(r'(\d{2})(,_)', r'{}\2'.format(str(repl_int)) , S, 1)
                S=re.sub('_', str(repl_int),S, Space_num)
        return S

S1="_,_,_,24"
S2="40,_,_,_,60"
S3=  "80,_,_,_,_"
S4="_,_,30,_,_,_,50,_,_"
S5="10_,_,30,_,_,_,50,_,_"
S6="_,_,30,_,_,_,50,_,_20"
S7="10_,_,30,_,_,_,50,_,_20"

print(curve_smoothing(S1))
print(curve_smoothing(S2))
print(curve_smoothing(S3))
print(curve_smoothing(S4))
print(curve_smoothing(S5))
print(curve_smoothing(S6))
print(curve_smoothing(S7))

Upvotes: 0

mujjiga
mujjiga

Reputation: 16856

Modular solution

# takes an array x and two indices a,b. 
# Replaces all the _'s with (x[a]+x[b])/(b-a+1)
def fun(x, a, b):
    if a == -1:
        v = float(x[b])/(b+1)
        for i in range(a+1,b+1):
            x[i] = v
    elif b == -1:
        v = float(x[a])/(len(x)-a)
        for i in range(a, len(x)):
            x[i] = v
    else:
        v = (float(x[a])+float(x[b]))/(b-a+1)
        for i in range(a,b+1):
            x[i] = v
    return x

def replace(text):
    # Create array from the string
    x = text.replace(" ","").split(",")
    # Get all the pairs of indices having number
    y = [i for i, v in enumerate(x) if v != '_']
    # Starting with _ ?
    if y[0] != 0:
        y = [-1] + y
    # Ending with _ ?
    if y[-1] != len(x)-1:
        y = y + [-1]    
    # run over all the pairs
    for (a, b) in zip(y[:-1], y[1:]): 
        fun(x,a,b)          
    return x

# Test cases
tests = [
    "_,_,_,24",
    "40,_,_,_,60",
    "80,_,_,_,_",
     "_,_,30,_,_,_,50,_,_"]

for i in tests:
    print (replace(i))

Upvotes: 5

Umbardacil
Umbardacil

Reputation: 31

First of all, you should specify a delimiter as argument in the split method, by default, it splits by spaces.

So "_,_,x,_,_,y,_".split() gives you ['_,_,x,_,_,y,_']

while "_,_,x,_,_,y,_".split(',') will give you ['_', '_', 'x', '_', '_', 'y', '_'].

Secondly, for the "middle" and "right" loop (for the right), you need to replace len with range.

Because of the division, you better use float instead of int

Since you use it for division, you better initialize denominator to 1.

In the last loop, a[q] = str((int(a[q])/(len(a)-flag+1))) (same with a[p]) should return an error because a[q] is "_". You need to use a variable to save the a[flag] value.

Each break should be in the else or if statement, otherwise, you'll pass the loop only once.

Finally, for better complexity, you can exit the middle_store asssignement from the j loop, to avoid asigning it every time.

TL;DR: Try this:

def blanks(S):
    a = S.split(',')
    count = 0
    middle_store = 0
    # left
    for i in range(len(a)):
        if a[i] == '_':
            count = count + 1  # find number of blanks to the left of a number
        else:
            for j in range(i + 1):
                # if there are n blanks to the left of the number speard the number equal over n+1 spaces
                a[j] = str((float(a[i]) / (count + 1)))
            middle_store = i
            middle_store_value = float(a[i])
            break

        # blanks in the middle
    denominator = 1
    flag = 0
    for k in range(middle_store + 1, len(a)):
        if a[k] != '_':
            denominator = (k + 1 - middle_store)
            flag = k
            break
    flag_value = float(a[flag])
    for p in range(middle_store, flag + 1):
        a[p] = str((middle_store_value+flag_value) / denominator)

    # blanks at the right
    last_value = float(a[flag])
    for q in range(flag, len(a)):
        a[q] = str(last_value / (len(a) - flag))

    return a

S=  "_,_,30,_,_,_,50,_,_"
print(blanks(S))

PS: did you even try to solve the errors ? or do you just wait for someone to solve your math problem ?

Upvotes: 2

Related Questions